[mpich-discuss] Problems with MPI and virtual functions in C++

Hélvio Vairinhos helvio.vairinhos at gmail.com
Wed Dec 12 13:23:12 CST 2012


Hi,

I came across a strange behaviour of MPI when I try to do a simple 
send/receive of an object of a class which contains virtual functions. I 
wrote a short code to exemplify what happens:


#include <mpi.h>
#include <iostream>
using namespace std;


class Pair {
   double elem[2];
public:
   Pair();
   Pair(const double&, const double&);
   //virtual
   Pair& operator += (const Pair&);
   void print();
   static MPI_Datatype mpi_type;
   static void Init();
   static void Finalize();
};


Pair::Pair()
{ elem[0]=0.; elem[1]=0.; }

Pair::Pair(const double& x, const double& y)
{ elem[0]=x; elem[1]=y; }

Pair& Pair::operator += (const Pair& q)
{ elem[0] += q.elem[0]; elem[1] += q.elem[1]; return *this; }

void Pair::print()
{ std::cout << "(" << elem[0] << "," << elem[1] << ")" << std::endl; }

MPI_Datatype Pair::mpi_type;

void Pair::Init()
{ MPI_Type_contiguous(2,MPI_DOUBLE,&mpi_type);
   MPI_Type_commit(&mpi_type); }

void Pair::Finalize()
{ MPI_Type_free(&mpi_type); }


int main() {
   int rank;
   MPI_Init(0,0);
   MPI_Comm_rank(MPI_COMM_WORLD,&rank);
   Pair::Init();
   Pair q;
   if (rank == 0) {
     q = Pair(1,2);
     MPI_Send(&q, 1, Pair::mpi_type, 1, 99, MPI_COMM_WORLD);
   }
   if (rank == 1) {
     q = Pair(3,4);
     MPI_Status status;
     MPI_Recv(&q, 1, Pair::mpi_type, 0, 99, MPI_COMM_WORLD, &status);
     q.print();
   }
   Pair::Finalize();
   MPI_Finalize();
   return 0;
}


I compiled it with mpic++, and ran it on 2 processes. Process 0 simply 
sends the pair q=(1,2) to process 1, which prints the result on the 
screen. The MPI datatype is contiguous with 2 MPI_DOUBLE components.

The program above behaves just fine, and prints the correct result 
(1,2). However, if I make the operator += virtual within the Pair class 
(i.e. if I uncomment the corresponding line above), then the process 1 
prints the result (1,4). In other words, process 0 only sends the 1st 
element of the pair. The 2nd element of the pair is only sent if I 
create an MPI datatype with 3 MPI_DOUBLE elements, i.e. if I use 
MPI_Type_contiguous(3,MPI_DOUBLE,&mpi_type). It behaves as if the buffer 
of MPI_Send starts at the address "&q-1" instead of "&q" when the 
virtual keyword is present.

Does anyone know why this happens, or if I am being careless at some 
point? I need to virtualize some functions in classes like this one, and 
I would like to trust that MPI communication is being done correctly.

Thank you in advance,

Helvio Vairinhos



More information about the discuss mailing list