PLearn 0.1
PLMPI.cc
Go to the documentation of this file.
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 :
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines