Send object with openMPI

2019-09-18 19:55发布

I'm using magick++ library to manage images. I want to distribute my algorithm using openMPI, is it possible to send objects?

for example in my code I have

  Image image(imgName);
  int w = image.columns();
  int h = image.rows();
  PixelPacket *pixels = image.getPixels(0, 0, w, h);

Can I send pixels with MPI_Send or Scatter of whatever? if yes with which datatype?

2条回答
虎瘦雄心在
2楼-- · 2019-09-18 20:24

I am no C++ programmer, but the following does what you are asking. Basically, I start 8 MPI process (I happen to use mpich) and the master reads in an image (Lena of course, from a PNG file) using Magick++ and then sends her to each of the slaves. The slaves receive Lena and rebuild her from the data they receive and each slave writes out its own local copy as a JPEG under a different name.

I cheated on the sizes because working out the sizes and passing those is easy but not germane to what I am demonstrating.

#include <cstdlib>
#include <iostream>
#include <Magick++.h>
#include "mpi.h"

using namespace std;

int main ( int argc, char *argv[] )
{
   int id,p;
   int number;

   // Initialise MPI
   MPI::Init (argc,argv);

   // Initialize ImageMagick and image processing stuff
   Magick::InitializeMagick(*argv);
   int row,col;
   Magick::Image image;
   int bytes=512*512*3;           // I happen to know Lena is 512x512 and RGB - i.e. 3 bytes/pixel
   unsigned char buffer[bytes];

   //  Get the number of processes
   p = MPI::COMM_WORLD.Get_size();

   //  Get the individual process ID
   id = MPI::COMM_WORLD.Get_rank();

   // Master will read in Lena and send her to all slaves
   if(id==0) 
   {
      cout << "MASTER: The number of processes is " << p << endl;
      // Read in Lena and put her in a buffer to send via MPI
      image.read("lena.png");

      // Convert Lena to a bunch of bytes
      image.write(0,0,512,512,"RGB",Magick::CharPixel,buffer);

      // Send the luscious Lena to all slaves
      for(int z=1;z<p;z++){
         cout << "MASTER: Sending Lena to slave " << z << endl;
         MPI_Send(buffer,bytes,MPI_BYTE,z,0,MPI_COMM_WORLD);
      }
   }else{
      // All slaves will receive Lena and write her out as a JPEG
      cout << "Process:" << id << " Started and waiting for Lena..." << endl;
      MPI_Recv(buffer,bytes,MPI_BYTE,0,0,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
      cout << "Process:" << id << " Received Lena" << endl;

      // Rebuild Lena from the bunch of bytes and write to "Lena-Rebuilt-<id>.jpg"
      Magick::Image rebuilt(512,512,"RGB",Magick::CharPixel,buffer);
      char filename[100];
      sprintf(filename,"Lena-Rebuilt-%d.jpg",id);
      rebuilt.write(filename);
   }

   //  Terminate MPI
   MPI::Finalize();
   return 0;
}

My Makefile looks like this:

all:    main

run:    main
        mpirun -n 8 ./main

main:   main.cpp
        mpic++ main.cpp -o main $$(Magick++-config --cxxflags --libs)

It runs like this:

make run
mpirun -n 8 ./main
MASTER: The number of processes is 8
Process:1 Started and waiting for Lena...
Process:3 Started and waiting for Lena...
Process:4 Started and waiting for Lena...
Process:5 Started and waiting for Lena...
Process:7 Started and waiting for Lena...
Process:6 Started and waiting for Lena...
Process:2 Started and waiting for Lena...
MASTER: Sending Lena to slave 1
MASTER: Sending Lena to slave 2
Process:1 Received Lena
MASTER: Sending Lena to slave 3
Process:2 Received Lena
MASTER: Sending Lena to slave 4
Process:3 Received Lena
MASTER: Sending Lena to slave 5
Process:4 Received Lena
MASTER: Sending Lena to slave 6
Process:5 Received Lena
MASTER: Sending Lena to slave 7
Process:6 Received Lena
Process:7 Received Lena

And the outputs look like this:

-rw-r--r--@ 1 mark  staff  150467 23 Oct 15:34 lena.png
-rw-r--r--  1 mark  staff    1786 23 Oct 17:04 main.cpp
-rwxr-xr-x  1 mark  staff   51076 23 Oct 17:14 main
-rw-r--r--@ 1 mark  staff   64755 23 Oct 17:14 Lena-Rebuilt-7.jpg
-rw-r--r--@ 1 mark  staff   64755 23 Oct 17:14 Lena-Rebuilt-6.jpg
-rw-r--r--@ 1 mark  staff   64755 23 Oct 17:14 Lena-Rebuilt-5.jpg
-rw-r--r--@ 1 mark  staff   64755 23 Oct 17:14 Lena-Rebuilt-4.jpg
-rw-r--r--@ 1 mark  staff   64755 23 Oct 17:14 Lena-Rebuilt-3.jpg
-rw-r--r--@ 1 mark  staff   64755 23 Oct 17:14 Lena-Rebuilt-2.jpg
-rw-r--r--@ 1 mark  staff   64755 23 Oct 17:14 Lena-Rebuilt-1.jpg
查看更多
做个烂人
3楼-- · 2019-09-18 20:27

In general, unless you have a special library that's doing packing for you, it's never possible to send a specialized object in MPI. The built-in datatypes are listed in the MPI Standard (MPI 3.0 page 665, Defined Values and Handles has a list), but at a high level, they're:

  • MPI_CHAR
  • MPI_INT
  • MPI_FLOAT
  • MPI_DOUBLE
  • MPI_BYTE

There are a lot more than that, but most of them end up being something like that.

You can take those types and put them together to make your own custom datatypes. For instance, if you know that you're going to send a bunch of structs that contain something like:

{
    int index;
    char[100] name;
    double value;
}

You can construct a type to hold that, it would be a contiguous type for the name and then a struct type for the overall datatype (which would contain the int, the type you construct for the name, and the double).

All you'd have to do is create a datatype which describes your PixelPacket.

查看更多
登录 后发表回答