Zoltan 2 Version 0.5
AlltoAll.cpp
Go to the documentation of this file.
00001 // @HEADER
00002 //
00003 // ***********************************************************************
00004 //
00005 //   Zoltan2: A package of combinatorial algorithms for scientific computing
00006 //                  Copyright 2012 Sandia Corporation
00007 //
00008 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00009 // the U.S. Government retains certain rights in this software.
00010 //
00011 // Redistribution and use in source and binary forms, with or without
00012 // modification, are permitted provided that the following conditions are
00013 // met:
00014 //
00015 // 1. Redistributions of source code must retain the above copyright
00016 // notice, this list of conditions and the following disclaimer.
00017 //
00018 // 2. Redistributions in binary form must reproduce the above copyright
00019 // notice, this list of conditions and the following disclaimer in the
00020 // documentation and/or other materials provided with the distribution.
00021 //
00022 // 3. Neither the name of the Corporation nor the names of the
00023 // contributors may be used to endorse or promote products derived from
00024 // this software without specific prior written permission.
00025 //
00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037 //
00038 // Questions? Contact Karen Devine      (kddevin@sandia.gov)
00039 //                    Erik Boman        (egboman@sandia.gov)
00040 //                    Siva Rajamanickam (srajama@sandia.gov)
00041 //
00042 // ***********************************************************************
00043 //
00044 // @HEADER
00045 
00046 // TODO: doxygen comments
00047 //     make this a real unit test that gives helpful information if it fails
00048 //     and uses different template values
00049 
00050 #include <Zoltan2_Environment.hpp>   
00051 #include <Zoltan2_AlltoAll.hpp>   
00052 #include <Zoltan2_TestHelpers.hpp>   
00053 
00054 #include <iostream>
00055 #include <algorithm>
00056 #include <vector>
00057 #include <string>
00058 
00059 #include <Teuchos_RCP.hpp>   
00060 #include <Teuchos_ArrayRCP.hpp>   
00061 #include <Teuchos_Comm.hpp>   
00062 #include <Teuchos_DefaultComm.hpp>   
00063 
00064 using namespace std;
00065 
00066 int main(int argc, char *argv[])
00067 {
00068   Teuchos::GlobalMPISession session(&argc, &argv);
00069   Teuchos::RCP<const Teuchos::Comm<int> > comm = 
00070     Teuchos::DefaultComm<int>::getComm();
00071 
00072   int rank = comm->getRank();
00073   int nprocs = comm->getSize();
00074 
00075   Teuchos::RCP<const Zoltan2::Environment> envPtr = 
00076     Teuchos::rcp(new Zoltan2::Environment);
00077 
00078   int errcode = 0;
00079   if (!errcode){
00080 
00081     // test of Zoltan2::AlltoAll using a Scalar type (ints)
00082   
00083     int *sendBuf = new int [2*nprocs];
00084     
00085     Teuchos::ArrayView<const int> sendBufView(sendBuf, 2*nprocs);
00086   
00087     for (int i=0, j=1; i < 2*nprocs ; i+=2,j++){
00088       sendBuf[i] = j*10;
00089       sendBuf[i+1] = j*10 + 1;
00090     } 
00091   
00092     Teuchos::ArrayRCP<int> recvBuf;
00093     
00094     Zoltan2::AlltoAll<int>(*comm, *envPtr,
00095         sendBufView,    // ints to send from this process to all the others
00096         2,              // two ints per process
00097         recvBuf);       // will be allocated and filled in AlltoAll
00098 
00099     delete [] sendBuf;
00100   
00101     int *inBuf = recvBuf.get();
00102   
00103     int myvals[2] = {(rank+1) * 10, (rank+1) * 10 + 1};
00104   
00105     for (int i=0; i < 2*nprocs; i+=2){
00106       if (inBuf[i] != myvals[0] && inBuf[i+1] != myvals[1]){
00107         errcode = 1;
00108         break;
00109       }
00110     }
00111   }
00112 
00113   TEST_FAIL_AND_EXIT(*comm, errcode==0, "ints", errcode);
00114 
00115   if (!errcode){
00116 
00117     // test of Zoltan2::AlltoAll using a non-Scalar type for which
00118     //  SerializationTraits are defined in Teuchos (std::pair).
00119   
00120     std::pair<int, int> *outBufPair = new std::pair<int, int> [nprocs];
00121 
00122     Teuchos::ArrayView< const std::pair<int, int> > sendBufPair(
00123       outBufPair, nprocs);
00124   
00125     for (int i=0,j=1; i < nprocs ; i++,j++){
00126       outBufPair[i].first = j*10;
00127       outBufPair[i].second = j*10 + 1;
00128     } 
00129   
00130     Teuchos::ArrayRCP< std::pair<int, int> > recvBufPair;
00131     
00132     Zoltan2::AlltoAll<std::pair<int, int> >(*comm, *envPtr,
00133         sendBufPair,    // ints to send from this process to all the others
00134         1,              // one pair per process
00135         recvBufPair);   // will be allocated and filled in AlltoAll
00136 
00137     delete [] outBufPair;
00138   
00139     std::pair<int, int > *inBufPair = recvBufPair.get();
00140 
00141     int myvals[2] = {(rank+1) * 10, (rank+1) * 10 + 1};
00142   
00143     for (int i=0; i < nprocs; i++){
00144       if (inBufPair[i].first != myvals[0] && inBufPair[i].second != myvals[1]){
00145         errcode = 2;
00146         break;
00147       }
00148     }
00149   }
00150 
00151   TEST_FAIL_AND_EXIT(*comm, errcode==0, "pairs", errcode);
00152 
00153   if (!errcode){
00154 
00155     // test of Zoltan2::AlltoAll using a non-Scalar type for which
00156     //  SerializationTraits are NOT defined in Teuchos (unsigned short).
00157   
00158     unsigned short *data = new unsigned short [nprocs];
00159 
00160     Teuchos::ArrayView< const unsigned short > sendBuf(data, nprocs);
00161   
00162     for (int i=0,j=1; i < nprocs ; i++,j++)
00163       data[i] = j*10;
00164   
00165     Teuchos::ArrayRCP< unsigned short > recvBuf;
00166     
00167     Zoltan2::AlltoAll<unsigned short>(*comm, *envPtr,
00168         sendBuf, 1, recvBuf); 
00169 
00170     delete [] data;
00171   
00172     unsigned short *inBuf = recvBuf.get();
00173 
00174     int myvals = (rank+1) * 10;
00175   
00176     for (int i=0; i < nprocs; i++){
00177       if (inBuf[i] != myvals){
00178         errcode = 3;
00179         break;
00180       }
00181     }
00182   }
00183 
00184   TEST_FAIL_AND_EXIT(*comm, errcode==0, "ushort", errcode);
00185 
00186   if (!errcode){
00187 
00188     // test of Zoltan2::AlltoAllv (different sized messages) using a Scalar type
00189 
00190     int myMsgSizeBase=rank*nprocs + 1;
00191     int *outMsgSizes = new int [nprocs];
00192     long totalOut = 0;
00193 
00194     for (int p=0; p < nprocs; p++){
00195       outMsgSizes[p] = myMsgSizeBase + p;
00196       totalOut += outMsgSizes[p];
00197     }
00198     Teuchos::ArrayView<const int> sendCount(outMsgSizes, nprocs);
00199   
00200     int *outBuf = new int [totalOut];
00201   
00202     int *out = outBuf;
00203     for (int p=0; p < nprocs; p++){
00204       for (int i=0; i < outMsgSizes[p]; i++){
00205         *out++ = p+rank;
00206       }
00207     }
00208     Teuchos::ArrayView<const int> sendBuf(outBuf, totalOut);
00209   
00210     Teuchos::ArrayRCP<int> recvCount;
00211     Teuchos::ArrayRCP<int> recvBuf;
00212     
00213     Zoltan2::AlltoAllv<int>(*comm, *envPtr,
00214                   sendBuf,    
00215                   sendCount,   
00216                   recvBuf,
00217                   recvCount);
00218 
00219     delete [] outBuf;
00220     delete [] outMsgSizes;
00221   
00222     int *inMsgSizes = recvCount.get();
00223     int *inBuf = recvBuf.get();
00224 
00225     for (int p=0; p < nprocs; p++){
00226       for (int i=0; i < inMsgSizes[p]; i++){
00227         if (*inBuf++ != rank+p){
00228           errcode = 4;
00229           break;
00230         }
00231       }
00232     }
00233   }
00234 
00235   TEST_FAIL_AND_EXIT(*comm, errcode==0, "int", errcode);
00236 
00237   if (!errcode){
00238 
00239     // test of Zoltan2::AlltoAllv using strings - which can not
00240     //    be serialized by Teuchos.
00241     //  Rank p sends p messages to each process.
00242 
00243     int nstrings = nprocs * rank;
00244     string *sendStrings = NULL;
00245 
00246     if (nstrings > 0)
00247       sendStrings = new string [nstrings];
00248 
00249     ostringstream myMessage;
00250     myMessage << "message from process " << rank;
00251 
00252     for (int i=0; i < nstrings; i++)
00253       sendStrings[i] = myMessage.str();
00254 
00255     int *counts = new int [nprocs];
00256     for (int i=0; i < nprocs ; i++)
00257       counts[i] = rank;
00258 
00259     Teuchos::ArrayView<const string> sendBuf(sendStrings, nstrings);
00260     Teuchos::ArrayView<const int> sendCount(counts, nprocs);
00261 
00262     Teuchos::ArrayRCP<string> recvBuf;
00263     Teuchos::ArrayRCP<int> recvCounts;
00264 
00265     Zoltan2::AlltoAllv<string>(*comm, *envPtr,
00266         sendBuf,    
00267         sendCount,   
00268         recvBuf,
00269         recvCounts);
00270 
00271     delete [] sendStrings;
00272     delete [] counts;
00273   
00274     int next = 0;
00275     for (int i=0; i < nprocs; i++){
00276       if (recvCounts[i] != i){
00277         errcode = 5;
00278         break;
00279       }
00280       ostringstream msg;
00281       msg << "message from process " << i;
00282       for (int j=0; j < recvCounts[i]; j++){
00283         if (recvBuf[next++] != msg.str()){
00284           errcode = 6;
00285           break;
00286         }
00287       }
00288     }
00289   }
00290 
00291   TEST_FAIL_AND_EXIT(*comm, errcode==0, "strings", errcode);
00292 
00293   if (rank == 0){
00294     if (errcode)
00295       std::cout << "FAIL" << std::endl;
00296     else
00297       std::cout << "PASS" << std::endl;
00298   }
00299 
00300   return errcode;
00301 }