PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // PLearn (A C++ Machine Learning Library) 00004 // Copyright (C) 2001 Pascal Vincent 00005 // 00006 00007 // Redistribution and use in source and binary forms, with or without 00008 // modification, are permitted provided that the following conditions are met: 00009 // 00010 // 1. Redistributions of source code must retain the above copyright 00011 // notice, this list of conditions and the following disclaimer. 00012 // 00013 // 2. Redistributions in binary form must reproduce the above copyright 00014 // notice, this list of conditions and the following disclaimer in the 00015 // documentation and/or other materials provided with the distribution. 00016 // 00017 // 3. The name of the authors may not be used to endorse or promote 00018 // products derived from this software without specific prior written 00019 // permission. 00020 // 00021 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 00022 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00023 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 00024 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00025 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00026 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00027 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00028 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00029 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00030 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00031 // 00032 // This file is part of the PLearn library. For more information on the PLearn 00033 // library, go to the PLearn Web site at www.plearn.org 00034 00035 /* ******************************************************* 00036 * $Id: PLMPI.cc 8789 2008-04-09 19:44:18Z nouiz $ 00037 * This file is part of the PLearn library. 00038 ******************************************************* */ 00039 00040 #include "PLMPI.h" 00041 #include <plearn/base/plerror.h> 00042 #include <plearn/io/FdPStreamBuf.h> 00043 #include <plearn/io/PStream.h> 00044 #include <plearn/math/Mat.h> 00045 00046 #include "string.h" 00047 #include <stdio.h> 00048 namespace PLearn { 00049 using namespace std; 00050 00051 00052 streambuf* PLMPI::new_cin_buf = 0; 00053 00054 #if USING_MPI 00055 bool PLMPI::using_mpi = true; 00056 #else 00057 bool PLMPI::using_mpi = false; 00058 #endif 00059 00060 bool PLMPI::synchronized = true; 00061 00062 int PLMPI::size = 0; 00063 int PLMPI::rank = 0; 00064 00065 PStream PLMPI::mycout; 00066 PStream PLMPI::mycerr; 00067 PStream PLMPI::mycin; 00068 00069 int PLMPI::tag = 2909; 00070 00071 void PLMPI::init(int* argc, char*** argv) 00072 { 00073 #ifndef WIN32 00074 mycin = new FdPStreamBuf(0, -1); 00075 mycout = new FdPStreamBuf(-1, 1); 00076 mycerr = new FdPStreamBuf(-1, 2, false, false); 00077 00078 #if USING_MPI 00079 MPI_Init( argc, argv ); 00080 MPI_Comm_size( MPI_COMM_WORLD, &size) ; 00081 MPI_Comm_rank( MPI_COMM_WORLD, &rank ); 00082 if(rank!=0) 00083 { 00084 cout.rdbuf(nullout.rdbuf()); 00085 cin.rdbuf(nullin.rdbuf()); 00086 } 00087 #endif 00088 00089 #endif // WIN32 00090 } 00091 00092 void PLMPI::finalize() 00093 { 00094 #if USING_MPI 00095 MPI_Finalize(); 00096 #endif 00097 } 00098 00099 00100 void PLMPI::exchangeBlocks(double* data, int n, int blocksize, double* buffer) 00101 { 00102 //#if USING_MPI 00103 int blockstart = PLMPI::rank*blocksize; 00104 //fprintf(stderr,"blockstart = %d\n",blockstart); 00105 int theblocksize = blocksize; 00106 int diff=n-blockstart; 00107 if (blocksize>diff) theblocksize=diff; 00108 if (theblocksize<=0) 00109 PLERROR("PLMPI::exchangeBlocks with block of size %d (b=%d,n=%d,r=%d,N=%d)", 00110 theblocksize,blocksize,n,PLMPI::rank,PLMPI::size); 00111 //fprintf(stderr,"theblocksize = %d\n",theblocksize); 00112 if (blocksize*PLMPI::size==n && buffer) 00113 { 00114 memcpy(buffer,&data[blockstart],theblocksize*sizeof(double)); 00115 #if USING_MPI 00116 MPI_Allgather(buffer,blocksize,MPI_DOUBLE, 00117 data,blocksize,MPI_DOUBLE,MPI_COMM_WORLD); 00118 #endif 00119 } 00120 else 00121 { 00122 for (int i=0;i<PLMPI::size;i++) 00123 { 00124 int bstart = i*blocksize; 00125 diff = n-bstart; 00126 int bsize = blocksize; 00127 if (bsize>diff) bsize=diff; 00128 //if (i==PLMPI::rank) 00129 //{ 00130 //fprintf(stderr,"start broadcast of %d, bstart=%d, size=%d\n",i,bstart,bsize); 00131 //for (int j=0;j<bsize;j++) 00132 //cerr << data[bstart+j] << endl; 00133 //} 00134 #if USING_MPI 00135 MPI_Bcast(&data[bstart],bsize,MPI_DOUBLE,i,MPI_COMM_WORLD); 00136 #endif 00137 //printf("done broadcast of %d",i); 00138 } 00139 } 00140 //#endif 00141 } 00142 00143 void PLMPI::exchangeBlocks(float* data, int n, int blocksize, float* buffer) 00144 { 00145 //#if USING_MPI 00146 int blockstart = PLMPI::rank*blocksize; 00147 //fprintf(stderr,"blockstart = %d\n",blockstart); 00148 int theblocksize = blocksize; 00149 int diff=n-blockstart; 00150 if (blocksize>diff) theblocksize=diff; 00151 if (theblocksize<=0) 00152 PLERROR("PLMPI::exchangeBlocks with block of size %d (b=%d,n=%d,r=%d,N=%d)", 00153 theblocksize,blocksize,n,PLMPI::rank,PLMPI::size); 00154 //fprintf(stderr,"theblocksize = %d\n",theblocksize); 00155 if (blocksize*PLMPI::size==n && buffer) 00156 { 00157 memcpy(buffer,&data[blockstart],theblocksize*sizeof(float)); 00158 #if USING_MPI 00159 MPI_Allgather(buffer,blocksize,MPI_FLOAT, 00160 data,blocksize,MPI_FLOAT,MPI_COMM_WORLD); 00161 #endif 00162 } 00163 else 00164 { 00165 for (int i=0;i<PLMPI::size;i++) 00166 { 00167 int bstart = i*blocksize; 00168 diff = n-bstart; 00169 int bsize = blocksize; 00170 if (bsize>diff) bsize=diff; 00171 //if (i==PLMPI::rank) 00172 //{ 00173 //fprintf(stderr,"start broadcast of %d, bstart=%d, size=%d\n",i,bstart,bsize); 00174 //for (int j=0;j<bsize;j++) 00175 //cerr << data[bstart+j] << endl; 00176 //} 00177 #if USING_MPI 00178 MPI_Bcast(&data[bstart],bsize,MPI_FLOAT,i,MPI_COMM_WORLD); 00179 #endif 00180 //printf("done broadcast of %d",i); 00181 } 00182 } 00183 //#endif 00184 } 00185 00186 void PLMPI::exchangeColumnBlocks(Mat sourceBlock, Mat destBlocks) 00187 { 00188 #if USING_MPI 00189 int width = sourceBlock.width(); 00190 int length = sourceBlock.length(); 00191 00192 int total_width = destBlocks.width(); 00193 00194 if (total_width%PLMPI::size == 0) // dest width is a multiple of size 00195 { 00196 for (int i=0; i<length; i++) 00197 { 00198 MPI_Allgather(sourceBlock[i],width,PLMPI_REAL, 00199 destBlocks[i],width,PLMPI_REAL,MPI_COMM_WORLD); 00200 } 00201 } 00202 else // last block has different width 00203 { 00204 int size_minus_one = PLMPI::size-1; 00205 int* counts = (int*)malloc(sizeof(int)*PLMPI::size); 00206 int* displs = (int*)malloc(sizeof(int)*PLMPI::size); 00207 int* ptr_counts = counts; 00208 int* ptr_displs = displs; 00209 int norm_width = total_width / PLMPI::size + 1; // width of all blocks except last 00210 int last_width = total_width - norm_width*size_minus_one; // width of last block 00211 if (last_width<=0) 00212 PLERROR("In PLMPI::exchangeColumnsBlocks: unproper choice of processes (%d) for matrix width (%d) leads " 00213 "to width = %d for first mats and width = %d for last mat.",PLMPI::size,total_width,norm_width,last_width); 00214 // sanity check 00215 if (PLMPI::rank==size_minus_one) 00216 { 00217 if (width!=last_width) 00218 PLERROR("In PLMPI::exchangeColumnsBlocks: width of last block is %d, should be %d.",width,last_width); 00219 } 00220 else 00221 if (width!=norm_width) 00222 PLERROR("In PLMPI::exchangeColumnsBlocks: width of block %d is %d, should be %d.",PLMPI::rank,width,last_width); 00223 for (int i=0;i<size_minus_one;i++) 00224 { 00225 *ptr_counts++ = norm_width; 00226 *ptr_displs++ = norm_width*i; 00227 } 00228 // last block 00229 *ptr_counts = last_width; 00230 *ptr_displs = norm_width*size_minus_one; 00231 for (int i=0; i<length; i++) 00232 { 00233 MPI_Allgatherv(sourceBlock[i],width,PLMPI_REAL, 00234 destBlocks[i],counts,displs,PLMPI_REAL,MPI_COMM_WORLD); 00235 } 00236 free(counts); 00237 free(displs); 00238 } 00239 #else 00240 PLWARNING("PLMPI::exchangeColumnsBlocks: in order to use this function, you should recompile with the flag USING_MPI set to 1."); 00241 #endif 00242 } 00243 00244 00245 00246 00247 00248 00249 00250 00251 00252 } // end of namespace PLearn 00253 00254 00255 /* 00256 Local Variables: 00257 mode:c++ 00258 c-basic-offset:4 00259 c-file-style:"stroustrup" 00260 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00261 indent-tabs-mode:nil 00262 fill-column:79 00263 End: 00264 */ 00265 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :