Отправить объект с openMPI
Я использую библиотеку magick++ для управления изображениями. Я хочу распространять свой алгоритм с использованием openMPI, возможно ли отправлять объекты?
например в моем коде у меня есть
Image image(imgName);
int w = image.columns();
int h = image.rows();
PixelPacket *pixels = image.getPixels(0, 0, w, h);
Могу ли я отправить pixels
с MPI_Send или Scatter чего угодно? если да, то с каким типом данных?
2 ответа
Я не программист C++, но следующее делает то, что вы просите. В основном, я запускаю процесс 8 MPI (я использую mpich
) и мастер читает изображение (Лена, конечно, из PNG
файл) с помощью Magick++, а затем отправляет ее каждому из рабов. Рабы получают Лену и восстанавливают ее из данных, которые они получают, и каждый раб записывает свою собственную локальную копию как JPEG
под другим именем.
Я изменил размерам, потому что определить размеры и передать их легко, но это не относится к тому, что я демонстрирую.
#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;
}
мой Makefile
выглядит так:
all: main
run: main
mpirun -n 8 ./main
main: main.cpp
mpic++ main.cpp -o main $$(Magick++-config --cxxflags --libs)
Это работает так:
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
И результаты выглядят так:
-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
В общем, если у вас нет специальной библиотеки, которая выполняет упаковку, вы никогда не сможете отправить специализированный объект в MPI. Встроенные типы данных перечислены в стандарте MPI (MPI 3.0 на стр. 665, список "Определенные значения и дескрипторы"), но на высоком уровне они:
MPI_CHAR
MPI_INT
MPI_FLOAT
MPI_DOUBLE
MPI_BYTE
Их намного больше, но большинство из них в итоге становятся чем-то подобным.
Вы можете взять эти типы и собрать их вместе, чтобы создать свои собственные типы данных. Например, если вы знаете, что собираетесь отправить группу структур, содержащих что-то вроде:
{
int index;
char[100] name;
double value;
}
Вы можете создать тип для хранения этого, это будет непрерывный тип для имени, а затем структурный тип для общего типа данных (который будет содержать int, тип, который вы создаете для имени, и тип double).
Все, что вам нужно сделать, это создать тип данных, который описывает ваш PixelPacket
,