0

I'm trying to send a std::list<int> back and forth between the master and slave. But I'm unsure how to create the MPI datatype and pass the list to the slave. I'd like to do this without using another library like boost. I'm trying to work off of this post but I haven't been able to get to work with the list. Below is the code I'm working with.

#include <iostream>
#include <list>
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>

using namespace std;

int main(int argc, char **argv)
{
int rank, size, tag, rc, i;
MPI_Status status;
char message[20];
char new_message[20];
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
tag=7;

if (rank==0) {
    strcpy(message, "Hello, world");
    for (int i=1; i<size; ++i){
        list<int> rand_list;
        list<int>::iterator it = rand_list.end();
        list<int> *lt_ptr = &rand_list;
        for(int j = 0; j < 5; ++j)
        {
             int r;
             r = rand();
             rand_list.push_front(r);
             it++;
        }
        //Instead of sending the string I'd like to send the list of random ints
        MPI_Send(message, 13, MPI_CHAR, i, tag, MPI_COMM_WORLD);
        MPI_Recv(new_message, 13, MPI_CHAR, i, tag, MPI_COMM_WORLD, &status);
        cout << "master: " << new_message << endl;
        }
}
else{
   // slaves processes
   rc = MPI_Recv(message, 13, MPI_CHAR, 0, tag, MPI_COMM_WORLD, &status);
   cout << "node " << rank << ": " << message << endl;
   strcpy(new_message, "Goodbye, world");
   // code to manipulate the lists and send back to the master process
   rc = MPI_Send(new_message, 13, MPI_CHAR, 0, tag, MPI_COMM_WORLD);
   }
MPI_Finalize();
}

Below are the commands I used to compile and run.

mpic++ mpi_prog.cpp -o mpi_prog.o
mpirun -np 5 mpi_prog.o
Community
  • 1
  • 1
user2743
  • 1,423
  • 3
  • 22
  • 34
  • 1
    If you just use a `std::vector` instead of `std::list`, this becomes trivial. The send buffer is `&rand_vec[0]`, and the count is `rand_vec.size()`. Is there a particular need to use a list? – Phil Miller Jun 12 '16 at 17:52

2 Answers2

0

The easiest way to send a list is probably by sending the length of the list, which you have as 5, and then a loop over the elements sending them one by one. This would have pretty poor performance, but using a list is probably a problematic design choice for many reasons.

Since you're also looping over the processes one by one in the master, sending them each different numbers, you may be better served with a different design overall. For your particular use case, how about generating the random numbers in parallel on the processes that will actually use them. There are purpose-design parallel random number generation algorithms, and advanceable random number generators that you could tell each slave how far to skip ahead in the stream so they don't overlap.

Phil Miller
  • 36,389
  • 13
  • 67
  • 90
0

Why do you want to use std::list here ? std::vector seems more appropriate, data is stored contiguously and it should work directly with MPI. You are overcomplicating things and by the way prefer using std::uniform_int_distribution rather than std::rand.

Your master code to fill random vector should look like something like that :

std::vector<int> v(5);
std::random_device rd;
std::mt19937 gen(rd()); // mersenne twister engine
std::uniform_int_distribution<> dis;
std::generate(v.begin(), v.end(), [&](){ return dis(gen); }); // fill the vector with random values

Your master node can call directly in MPI :

MPI_Send(&v[0], v.size(), MPI_INT, i, tag, MPI_COMM_WORLD);

The slave node code:

MPI_Recv(&v[0], v.size(), MPI_INT, 0, tag, MPI_COMM_WORLD, &status);

I am not sure this is what you want to do. Your master will initialize size different vectors with random values and will send each of them to one slave node. Each vector received by a slave will be different. Is it correct ?

coincoin
  • 4,595
  • 3
  • 23
  • 47