Re: [mpich-discuss] Problems with MPI and virtual functions in C++
Classes/structs that have virtual functions have a different memory layout than structures/classes without them. In your code below, you're assuming that the class Pair has a memory layout of 2 doubles. This happens to be the case when there are no virtual functions in the class. However, if you add a virtual function, the memory layout changes. The class now also contains information about its runtime type (i.e. Pair). You can fix this by using &p->elem[0] as the address of the data you want to send/receive. Dries * Hélvio Vairinhos <[email protected]> [2012-12-12 19:23:12]:
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 _______________________________________________ discuss mailing list [email protected] To manage subscription options or unsubscribe: https://lists.mpich.org/mailman/listinfo/discuss
participants (1)
-
Dries Kimpe