LCOV - code coverage report
Current view: top level - synthesis/Parallel - MPITransport.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 0 282 0.0 %
Date: 2024-10-09 13:55:54 Functions: 0 36 0.0 %

          Line data    Source code
       1             : //# MPITransport.cc: class which define an MPI parallel transport layer
       2             : //# Copyright (C) 1998,1999,2000
       3             : //# Associated Universities, Inc. Washington DC, USA.
       4             : //#
       5             : //# This library is free software; you can redistribute it and/or modify it
       6             : //# under the terms of the GNU Library General Public License as published by
       7             : //# the Free Software Foundation; either version 2 of the License, or (at your
       8             : //# option) any later version.
       9             : //#
      10             : //# This library is distributed in the hope that it will be useful, but WITHOUT
      11             : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12             : //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
      13             : //# License for more details.
      14             : //#
      15             : //# You should have received a copy of the GNU Library General Public License
      16             : //# along with this library; if not, write to the Free Software Foundation,
      17             : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
      18             : //#
      19             : //# Correspondence concerning AIPS++ should be addressed as follows:
      20             : //#        Internet email: casa-feedback@nrao.edu.
      21             : //#        Postal address: AIPS++ Project Office
      22             : //#                        National Radio Astronomy Observatory
      23             : //#                        520 Edgemont Road
      24             : //#                        Charlottesville, VA 22903-2475 USA
      25             : //#
      26             : //# $Id$
      27             : 
      28             : #ifdef HAVE_MPI
      29             : 
      30             : #include <memory>
      31             : 
      32             : #include <casacore/casa/Containers/Record.h>
      33             : #include <casacore/casa/IO/AipsIO.h>
      34             : #include <casacore/casa/IO/MemoryIO.h>
      35             : 
      36             : #include <synthesis/Parallel/MPITransport.h>
      37             : #include <synthesis/Parallel/MPIError.h>
      38             : #include <synthesis/Parallel/Algorithm.h>
      39             : 
      40             : #include <mpi.h>
      41             : 
      42             : using std::shared_ptr;
      43             : using namespace casacore;
      44             : namespace casa { //# NAMESPACE CASA - BEGIN
      45             : 
      46           0 : MPITransport::MPITransport() : PTransport()
      47             : {
      48             : // Default constructor
      49             : //
      50             :   // Set default tag and source/destination
      51           0 :   setAnyTag();
      52           0 :   connectAnySource();
      53           0 : };
      54             : 
      55           0 : MPITransport::MPITransport(Int argc, Char *argv[]) : PTransport()
      56             : {
      57           0 :    if (debug_p) {
      58           0 :        cerr << "constructing MPITransport" << std::endl;
      59             :    }
      60             : // Construct from argc, argv
      61             : //
      62           0 :    int flag=0;
      63           0 :    MPI_Initialized(&flag);
      64             :    //cerr << "FLAG " << flag << endl;
      65           0 :    if((flag && isController()) || MPI_Init(&argc, &argv) == MPI_SUCCESS){
      66             :      //if(MPI_Init(&argc, &argv) == MPI_SUCCESS){
      67           0 :       MPI_Comm_rank(MPI_COMM_WORLD, &myCpu);
      68           0 :       MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
      69             :       // Set default tag and source/destination
      70           0 :       setAnyTag();
      71           0 :       connectAnySource();
      72             :    } else {
      73           0 :      throw MPIError("MPI Init failed!");
      74             :    }
      75           0 : }
      76             : 
      77           0 : MPITransport::~MPITransport(){
      78           0 :   if(!isFinalized())
      79           0 :     MPI_Finalize();
      80           0 : }
      81             : 
      82           0 : Bool MPITransport::isFinalized()
      83             : {
      84             :     int flag;
      85           0 :     MPI_Finalized(&flag);
      86           0 :     return Bool(flag);
      87             : }
      88             : 
      89           0 : Int MPITransport::anyTag()
      90             : {
      91             : // Return the value which indicates an unset tag
      92             : //
      93           0 :    return MPI_ANY_TAG;
      94             : };
      95             : 
      96           0 : Int MPITransport::anySource()
      97             : {
      98             : // Return the value which indicates an unset source
      99             : //
     100           0 :    return MPI_ANY_SOURCE;
     101             : };
     102             : 
     103             : // produce a contiguous vector of per-dimension sizes from a shape/Iposition
     104           0 : const std::vector<uInt> makeContiguousSizes(uInt ndim, const IPosition &ipos) {
     105           0 :     std::vector<uInt> sizes(ndim);
     106           0 :     for (uInt idx=0; idx<ndim; ++idx) {
     107           0 :         sizes[idx] = ipos[idx];
     108             :     }
     109           0 :     return sizes;
     110           0 : }
     111             : 
     112           0 : Int MPITransport::put(const Array<Float> &af){
     113           0 :    uInt ndim(af.ndim());
     114           0 :    setDestAndTag(sendTo, myOp);
     115           0 :    IPosition ipos = af.shape();
     116             :       // Send the number of dimensions
     117           0 :    MPI_Send((void *)&ndim, 1, MPI_UNSIGNED, sendTo, myOp, MPI_COMM_WORLD);
     118             :       // Send the shape vector
     119             :    // Don't feel tempted to send directly (void *)ipos.storage(). That doesn't give you
     120             :    // a contiguous sequence of size integers. You can get for example integers:
     121             :    // dim1, 0, dim2, 0, uninit, ...
     122             :    // etc.
     123             :    // Dangerous: MPI_Send((void *)ipos.storage(), ndim,  MPI_INT, sendTo, myOp,
     124           0 :    const auto &sizes = makeContiguousSizes(ndim, ipos);
     125           0 :    MPI_Send((void *)sizes.data(), ndim,  MPI_INT, sendTo, myOp,
     126             :             MPI_COMM_WORLD);
     127             :       // Send the data
     128             :    Bool deleteit;
     129           0 :    MPI_Send((void *)af.getStorage(deleteit), af.nelements(),  MPI_FLOAT,
     130             :              sendTo, myOp, MPI_COMM_WORLD);
     131           0 :    return(0);
     132           0 : }
     133             : 
     134           0 : Int MPITransport::put(const Array<Double> &af){
     135           0 :    uInt ndim(af.ndim());
     136           0 :    const IPosition ipos = af.shape();
     137           0 :    setDestAndTag(sendTo, myOp);
     138           0 :    MPI_Send((void *)&ndim, 1, MPI_UNSIGNED, sendTo, myOp, MPI_COMM_WORLD);
     139             :       // Send the shape vector
     140           0 :    const auto &sizes = makeContiguousSizes(ndim, ipos);
     141           0 :    MPI_Send((const void *)sizes.data(), ndim,  MPI_INT, sendTo, myOp,
     142             :             MPI_COMM_WORLD);
     143             :       // Send the data
     144             :    Bool deleteit;
     145           0 :    MPI_Send((void *)af.getStorage(deleteit), af.nelements(),  MPI_DOUBLE,
     146             :              sendTo, myOp, MPI_COMM_WORLD);
     147           0 :    return(0);
     148           0 : }
     149             : 
     150           0 : Int MPITransport::put(const Array<Int> &af){
     151           0 :    uInt ndim(af.ndim());
     152           0 :    IPosition ipos = af.shape();
     153           0 :    setDestAndTag(sendTo, myOp);
     154           0 :    MPI_Send((void *)&ndim, 1, MPI_UNSIGNED, sendTo, myOp, MPI_COMM_WORLD);
     155             :       // Send the shape vector
     156           0 :    const auto &sizes = makeContiguousSizes(ndim, ipos);
     157           0 :    MPI_Send((void *)sizes.data(), ndim,  MPI_INT, sendTo, myOp,
     158             :             MPI_COMM_WORLD);
     159             :       // Send the data
     160             :    Bool deleteit;
     161           0 :    MPI_Send((void *)af.getStorage(deleteit), af.nelements(),  MPI_INT,
     162             :              sendTo, myOp, MPI_COMM_WORLD);
     163           0 :    return(0);
     164           0 : }
     165             : 
     166           0 : Int MPITransport::put(const Array<Complex> &af){
     167           0 :    uInt ndim(af.ndim());
     168           0 :    setDestAndTag(sendTo, myOp);
     169           0 :    IPosition ipos = af.shape();
     170             :       // Send the number of dimensions
     171           0 :    MPI_Send((void *)&ndim, 1, MPI_UNSIGNED, sendTo, myOp, MPI_COMM_WORLD);
     172             :       // Send the shape vector
     173           0 :    const auto &sizes = makeContiguousSizes(ndim, ipos);
     174           0 :    MPI_Send((const void *)sizes.data(), ndim,  MPI_INT, sendTo, myOp,
     175             :             MPI_COMM_WORLD);
     176             :       // Send the data
     177             :    Bool deleteit;
     178           0 :    MPI_Send((void *)af.getStorage(deleteit), 2*af.nelements(),  MPI_FLOAT,
     179             :              sendTo, myOp, MPI_COMM_WORLD);
     180           0 :    return(0);
     181           0 : }
     182             : 
     183           0 : Int MPITransport::put(const Array<DComplex> &af){
     184           0 :    uInt ndim(af.ndim());
     185           0 :    setDestAndTag(sendTo, myOp);
     186           0 :    IPosition ipos = af.shape();
     187             :       // Send the number of dimensions
     188           0 :    MPI_Send((void *)&ndim, 1, MPI_UNSIGNED, sendTo, myOp, MPI_COMM_WORLD);
     189             :       // Send the shape vector
     190           0 :    const auto &sizes = makeContiguousSizes(ndim, ipos);
     191           0 :    MPI_Send((void *)sizes.data(), ndim,  MPI_INT, sendTo, myOp,
     192             :             MPI_COMM_WORLD);
     193             :       // Send the data
     194             :    Bool deleteit;
     195           0 :    MPI_Send((void *)af.getStorage(deleteit), 2*af.nelements(),  MPI_DOUBLE,
     196             :              sendTo, myOp, MPI_COMM_WORLD);
     197           0 :    return(0);
     198           0 : }
     199             : 
     200           0 : Int MPITransport::put(const Float &f){
     201           0 :    setDestAndTag(sendTo, myOp);
     202           0 :    MPI_Send((void *)&f, 1, MPI_FLOAT, sendTo, myOp, MPI_COMM_WORLD);
     203           0 :    return(0);
     204             : }
     205           0 : Int MPITransport::put(const Complex &f){
     206           0 :    setDestAndTag(sendTo, myOp);
     207           0 :    MPI_Send((void *)&f, 2, MPI_FLOAT, sendTo, myOp, MPI_COMM_WORLD);
     208           0 :    return(0);
     209             : }
     210           0 : Int MPITransport::put(const DComplex &f){
     211           0 :    setDestAndTag(sendTo, myOp);
     212           0 :    MPI_Send((void *)&f, 2, MPI_DOUBLE, sendTo, myOp, MPI_COMM_WORLD);
     213           0 :    return(0);
     214             : }
     215             : 
     216           0 : Int MPITransport::put(const Double &d){
     217           0 :    setDestAndTag(sendTo, myOp);
     218           0 :    MPI_Send((void *)&d, 1, MPI_DOUBLE, sendTo, myOp, MPI_COMM_WORLD);
     219           0 :    return(0);
     220             : }
     221           0 : Int MPITransport::put(const Int &i){
     222           0 :    setDestAndTag(sendTo, myOp);
     223             :    // warning: sstat set but not used!
     224           0 :    Int sstat = MPI_Send((void *)&i, 1, MPI_INT, sendTo, myOp, MPI_COMM_WORLD);
     225             :    (void) sstat; // warning: unused sstat
     226           0 :    return(0);
     227             : }
     228           0 : Int MPITransport::put(const Bool &b){
     229           0 :    setDestAndTag(sendTo, myOp);
     230           0 :    Int i(b);
     231             :    // warning: sstat set but not used!
     232           0 :    Int sstat = MPI_Send((void *)&i, 1, MPI_INT, sendTo, myOp, MPI_COMM_WORLD);
     233             :    (void) sstat; // warning: unused sstat
     234           0 :    return(0);
     235             : }
     236             : 
     237           0 : Int MPITransport::put(const Record &r){
     238           0 :    setDestAndTag(sendTo, myOp);
     239           0 :    auto buffer = std::make_shared<MemoryIO>();
     240           0 :    AipsIO rBuf(buffer);
     241           0 :    rBuf.putstart("MPIRecord",1);
     242           0 :    rBuf << r;
     243           0 :    rBuf.putend();
     244           0 :    uInt bytes2send=rBuf.getpos();
     245             :    //cerr << "Bytes 2 send " << bytes2send << endl;
     246             :    // warning: sstat set but not used!
     247           0 :    Int sstat = MPI_Send((void *)&bytes2send, 1, MPI_UNSIGNED, sendTo, myOp, MPI_COMM_WORLD);
     248           0 :    sstat = MPI_Send((void *)buffer->getBuffer(), bytes2send, MPI_UNSIGNED_CHAR, sendTo, myOp,
     249             :                     MPI_COMM_WORLD);
     250             :    (void) sstat; // warning: unused sstat
     251           0 :    return(0);
     252           0 : }
     253             : 
     254           0 : Int MPITransport::put(const String &s){
     255           0 :    uInt ndim(s.length());
     256           0 :    setDestAndTag(sendTo, myOp);
     257             :       // Send the length of the string
     258           0 :    MPI_Send((void *)&ndim, 1, MPI_UNSIGNED, sendTo, myOp, MPI_COMM_WORLD);
     259             :       // Send the characters
     260           0 :    MPI_Send((void *)s.chars(), ndim,  MPI_CHAR, sendTo, myOp,
     261             :             MPI_COMM_WORLD);
     262           0 :    return(0);
     263             : }
     264             : 
     265           0 : Int MPITransport::get(Array<Float> &af){
     266             :       // Get the number of dimensions
     267           0 :    setSourceAndTag(getFrom, myOp);
     268             :    MPI_Status status;
     269             :    uInt ndim;
     270           0 :    MPI_Recv(&ndim, 1, MPI_INT, getFrom, myOp, MPI_COMM_WORLD, &status);
     271             :       // Get the shape vector
     272           0 :    aTag = myOp = status.MPI_TAG;
     273           0 :    aWorker = getFrom = status.MPI_SOURCE;
     274           0 :    std::vector<uInt> ashape(ndim);
     275           0 :    MPI_Recv(ashape.data(), ndim, MPI_INT, getFrom, myOp, MPI_COMM_WORLD, &status);
     276             :       // Get the data
     277           0 :    Int nelements(1);
     278             :    {
     279           0 :    for(uInt i=0;i<ndim;i++){
     280           0 :       nelements *= ashape[i];
     281             :    }
     282             :    }
     283           0 :    Float *data = new Float[nelements];
     284           0 :    MPI_Recv(data, nelements, MPI_FLOAT, getFrom, myOp, MPI_COMM_WORLD,
     285             :             &status);
     286           0 :    IPosition ipos(ndim, ndim);
     287           0 :    for(uInt i=0;i<ndim;i++)
     288           0 :       ipos(i) = ashape[i];
     289           0 :    af.takeStorage(ipos, data, TAKE_OVER);
     290             : 
     291           0 :    return(status.MPI_SOURCE);
     292           0 : }
     293             : 
     294           0 : Int MPITransport::get(Array<Double> &af){
     295             :       // Get the number of dimensions
     296             :    MPI_Status status;
     297           0 :    setSourceAndTag(getFrom, myOp);
     298             :    uInt ndim;
     299           0 :    MPI_Recv(&ndim, 1, MPI_INT, getFrom, myOp, MPI_COMM_WORLD, &status);
     300             :       // Get the shape vector
     301           0 :    aTag = myOp = status.MPI_TAG;
     302           0 :    aWorker = getFrom = status.MPI_SOURCE;
     303           0 :    std::vector<uInt> ashape(ndim);
     304           0 :    MPI_Recv(ashape.data(), ndim, MPI_INT, getFrom, myOp, MPI_COMM_WORLD, &status);
     305             :       // Get the data
     306           0 :    Int nelements(1);
     307             :    {
     308           0 :    for(uInt i=0;i<ndim;i++){
     309           0 :       nelements *= ashape[i];
     310             :    }
     311             :    }
     312           0 :    Double *data = new Double[nelements];
     313           0 :    MPI_Recv(data, nelements, MPI_DOUBLE, getFrom, myOp, MPI_COMM_WORLD,
     314             :             &status);
     315           0 :    IPosition ipos(ndim, ndim);
     316           0 :    for(uInt i=0;i<ndim;i++)
     317           0 :       ipos(i) = ashape[i];
     318           0 :    af.takeStorage(ipos, data, TAKE_OVER);
     319             : 
     320           0 :    return(status.MPI_SOURCE);
     321           0 : }
     322             : 
     323           0 : Int MPITransport::get(Array<Complex> &af){
     324             :       // Get the number of dimensions
     325             :    MPI_Status status;
     326           0 :    setSourceAndTag(getFrom, myOp);
     327             :    uInt ndim;
     328           0 :    MPI_Recv(&ndim, 1, MPI_INT, getFrom, myOp, MPI_COMM_WORLD, &status);
     329             :       // Get the shape vector
     330           0 :    aTag = myOp = status.MPI_TAG;
     331           0 :    aWorker = getFrom = status.MPI_SOURCE;
     332           0 :    std::vector<uInt> ashape(ndim);
     333           0 :    MPI_Recv(ashape.data(), ndim, MPI_INT, getFrom, myOp, MPI_COMM_WORLD, &status);
     334             :       // Get the data
     335           0 :    Int nelements(1);
     336             :    {
     337           0 :    for(uInt i=0;i<ndim;i++){
     338           0 :       nelements *= ashape[i];
     339             :    }
     340             :    }
     341           0 :    Complex *data = new Complex[nelements];
     342           0 :    MPI_Recv(data, 2*nelements, MPI_FLOAT, getFrom, myOp, MPI_COMM_WORLD,
     343             :             &status);
     344           0 :    IPosition ipos(ndim, ndim);
     345           0 :    for(uInt i=0;i<ndim;i++)
     346           0 :       ipos(i) = ashape[i];
     347           0 :    af.takeStorage(ipos, data, TAKE_OVER);
     348             : 
     349           0 :    return(status.MPI_SOURCE);
     350           0 : }
     351             : 
     352           0 : Int MPITransport::get(Array<DComplex> &af){
     353             :       // Get the number of dimensions
     354             :    MPI_Status status;
     355             :    uInt ndim;
     356           0 :    setSourceAndTag(getFrom, myOp);
     357           0 :    MPI_Recv(&ndim, 1, MPI_INT, getFrom, myOp, MPI_COMM_WORLD, &status);
     358             :       // Get the shape vector
     359           0 :    aTag = myOp = status.MPI_TAG;
     360           0 :    aWorker = getFrom = status.MPI_SOURCE;
     361           0 :    std::vector<uInt> ashape(ndim);
     362           0 :    MPI_Recv(ashape.data(), ndim, MPI_INT, getFrom, myOp, MPI_COMM_WORLD, &status);
     363             :       // Get the data
     364           0 :    Int nelements(1);
     365             :    {
     366           0 :    for(uInt i=0;i<ndim;i++){
     367           0 :       nelements *= ashape[i];
     368             :    }
     369             :    }
     370           0 :    DComplex *data = new DComplex[nelements];
     371           0 :    MPI_Recv(data, 2*nelements, MPI_DOUBLE, getFrom, myOp, MPI_COMM_WORLD,
     372             :             &status);
     373           0 :    IPosition ipos(ndim, ndim);
     374           0 :    for(uInt i=0;i<ndim;i++)
     375           0 :       ipos(i) = ashape[i];
     376           0 :    af.takeStorage(ipos, data, TAKE_OVER);
     377             : 
     378           0 :    return(status.MPI_SOURCE);
     379           0 : }
     380             : 
     381           0 : Int MPITransport::get(Array<Int> &af){
     382             :       // Get the number of dimensions
     383             :    MPI_Status status;
     384             :    uInt ndim;
     385           0 :    setSourceAndTag(getFrom, myOp);
     386           0 :    MPI_Recv(&ndim, 1, MPI_INT, getFrom, myOp, MPI_COMM_WORLD, &status);
     387             :       // Get the shape vector
     388           0 :    aTag = myOp = status.MPI_TAG;
     389           0 :    aWorker = getFrom = status.MPI_SOURCE;
     390           0 :    std::vector<uInt> ashape(ndim);
     391           0 :    MPI_Recv(ashape.data(), ndim, MPI_INT, getFrom, myOp, MPI_COMM_WORLD, &status);
     392             :       // Get the data
     393           0 :    Int nelements(1);
     394             :    {
     395           0 :    for(uInt i=0;i<ndim;i++){
     396           0 :       nelements *= ashape[i];
     397             :    }
     398             :    }
     399           0 :    Int *data = new Int[nelements];
     400           0 :    MPI_Recv(data, nelements, MPI_INT, getFrom, myOp, MPI_COMM_WORLD,
     401             :             &status);
     402           0 :    IPosition ipos(ndim, ndim);
     403           0 :    for(uInt i=0;i<ndim;i++)
     404           0 :       ipos(i) = ashape[i];
     405           0 :    af.takeStorage(ipos, data, TAKE_OVER);
     406             : 
     407           0 :    return(status.MPI_SOURCE);
     408           0 : }
     409             : 
     410           0 : Int MPITransport::get(Float &f){
     411             :    MPI_Status status;
     412           0 :    setSourceAndTag(getFrom, myOp);
     413           0 :    MPI_Recv(&f, 1, MPI_FLOAT, getFrom, myOp, MPI_COMM_WORLD, &status);
     414           0 :    return(status.MPI_SOURCE);
     415             : }
     416             : 
     417           0 : Int MPITransport::get(Double &d){
     418             :    MPI_Status status;
     419           0 :    setSourceAndTag(getFrom, myOp);
     420           0 :    MPI_Recv(&d, 1, MPI_DOUBLE, getFrom, myOp, MPI_COMM_WORLD, &status);
     421           0 :    return(status.MPI_SOURCE);
     422             : }
     423             : 
     424           0 : Int MPITransport::get(Complex &f){
     425             :    MPI_Status status;
     426           0 :    setSourceAndTag(getFrom, myOp);
     427           0 :    MPI_Recv(&f, 2, MPI_FLOAT, getFrom, myOp, MPI_COMM_WORLD, &status);
     428           0 :    return(status.MPI_SOURCE);
     429             : }
     430             : 
     431           0 : Int MPITransport::get(DComplex &d){
     432             :    MPI_Status status;
     433           0 :    setSourceAndTag(getFrom, myOp);
     434           0 :    MPI_Recv(&d, 2, MPI_DOUBLE, getFrom, myOp, MPI_COMM_WORLD, &status);
     435           0 :    return(status.MPI_SOURCE);
     436             : }
     437             : 
     438           0 : Int MPITransport::get(Int &i){
     439           0 :    Int r_status(1);
     440             :    MPI_Status status;
     441           0 :    setSourceAndTag(getFrom, myOp);
     442           0 :    r_status = MPI_Recv(&i, 1, MPI_INT, getFrom, myOp, MPI_COMM_WORLD, &status);
     443             :    (void) r_status; // warning: unused r_status
     444           0 :    return(status.MPI_SOURCE);
     445             : }
     446             : 
     447           0 : Int MPITransport::get(Bool &b){
     448           0 :    Int r_status(1);
     449             :    MPI_Status status;
     450           0 :    setSourceAndTag(getFrom, myOp);
     451             :    Int i;
     452           0 :    r_status = MPI_Recv(&i, 1, MPI_INT, getFrom, myOp, MPI_COMM_WORLD, &status);
     453             :    (void) r_status; // warning: unused r_status
     454           0 :    if(i == 0)
     455           0 :       b = false;
     456             :    else
     457           0 :       b = true;
     458           0 :    return(status.MPI_SOURCE);
     459             : }
     460             : 
     461           0 : Int MPITransport::get(Record &r){
     462             :    MPI_Status status;
     463             :    (void) status; // warning: unused status
     464           0 :    setSourceAndTag(getFrom, myOp);
     465             :    // Get the size of the record in bytes
     466             :    uInt bytesSent;
     467           0 :    MPI_Recv(&bytesSent, 1, MPI_UNSIGNED, getFrom, myOp, MPI_COMM_WORLD, &status);
     468             :    // Now fill the buffer full of bytes from the record
     469           0 :    std::vector<uChar> buffer(bytesSent);
     470           0 :    MPI_Recv(buffer.data(), bytesSent, MPI_UNSIGNED_CHAR, getFrom, myOp, MPI_COMM_WORLD, &status);
     471           0 :    auto nBuf = std::make_shared<MemoryIO>(buffer.data(), bytesSent);
     472           0 :    AipsIO rBuf(nBuf);
     473           0 :    uInt version = rBuf.getstart("MPIRecord");
     474             :    (void)version; // warning: unused version
     475           0 :    rBuf >> r;
     476           0 :    rBuf.getend();
     477           0 :    return(0);
     478           0 : }
     479             : 
     480           0 : Int MPITransport::get(String &s){
     481             :    MPI_Status status;
     482             :    (void) status; // warning: unused status
     483           0 :    setSourceAndTag(getFrom, myOp);
     484             :       // Get the length of the string
     485             :    uInt i;
     486           0 :    MPI_Recv(&i, 1, MPI_UNSIGNED, getFrom, myOp, MPI_COMM_WORLD, &status);
     487             :    // Send the characters
     488           0 :    Char *theChars = new Char[i+1];
     489           0 :    MPI_Recv(theChars, i, MPI_CHAR, getFrom, myOp, MPI_COMM_WORLD, &status);
     490             : 
     491           0 :    *(theChars+i) = 0;
     492           0 :    s = theChars;
     493           0 :    delete [] theChars;
     494           0 :    return(status.MPI_SOURCE);
     495             : }
     496             : 
     497           0 : void MPITransport::setSourceAndTag(Int &source, Int &tag)
     498             : {
     499             : // Set source and tag for MPI_Recv commands
     500             : //
     501             :   // Message tag
     502           0 :   tag = aTag;
     503             : 
     504             :   // Source
     505           0 :   if (isController()) {
     506           0 :     source = aWorker;
     507             :   } else {
     508           0 :     source = controllerRank();
     509             :   };
     510           0 :   return;
     511             : };
     512             : 
     513           0 : void MPITransport::setDestAndTag(Int &dest, Int &tag)
     514             : {
     515             : // Set destination and tag for MPI_Send commands
     516             : //
     517             :   // Message tag
     518           0 :   if (aTag == anyTag()) {
     519           0 :     throw(AipsError("No tag set for MPI send command"));
     520             :   } else {
     521           0 :     tag = aTag;
     522             :   };
     523             : 
     524             :   // Destination
     525           0 :   if (isController()) {
     526           0 :     if (aWorker != anySource()) {
     527           0 :       dest = aWorker;
     528             :     } else {
     529           0 :       throw(AipsError("Invalid destination for MPI send command"));
     530             :     };
     531             :   } else {
     532           0 :     dest = controllerRank();
     533             :   };
     534           0 :   return;
     535             : };
     536             : 
     537             : 
     538             : } //# NAMESPACE CASA - END
     539             : 
     540             : #endif
     541             : 

Generated by: LCOV version 1.16