MPI 发送带有字节数组和整数的结构
MPI send struct with bytes array and integers
我想发送图像数据(unsigned char 数组)、宽度和高度从 0 级到 1 级。执行此操作的最佳方法是什么?我读过要在 MPI 中发送复杂的数据结构,我们可以使用打包数据或创建自己的数据类型。什么对我来说更好?
我试图通过创建一个新的数据类型来做到这一点。但我错了:Segmentation fault (signal 11)
。当我从我的结构中删除数组时,它就起作用了。那么发送这个数组有什么问题呢?
我的结构:
typedef struct MyImage {
int w;
int h;
unsigned char *data;
} image;
主要:
int main(int argc, char **argv) {
int size, rank;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
int blocksCount = 3;
int blocksLength[3] = {1, 1, 512 * 512 * 3};
// I also tried MPI_BYTE
MPI_Datatype types[3] = {MPI_INT, MPI_INT, MPI_UNSIGNED_CHAR};
MPI_Aint offsets[3];
MPI_Datatype custom_type;
offsets[0] = offsetof(image, w);
offsets[1] = offsetof(image, h);
offsets[3] = offsetof(image, data);
MPI_Type_create_struct(blocksCount, blocksLength, offsets, types, &custom_type);
MPI_Type_commit(&custom_type);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (rank == 0) {
Mat mat = imread("/home/user/image.jpg", CV_LOAD_IMAGE_COLOR);
image send;
send.w = mat.size().width;
send.h = mat.size().height;
send.data = mat.data;
MPI_Send(&send, 1, custom_type, 1, 0, MPI_COMM_WORLD);
}
if (rank == 1) {
image recv;
MPI_Status status;
MPI_Recv(&recv, 1, custom_type, 0, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
}
MPI_Type_free(&custom_type);
MPI_Finalize();
return 0;
}
发送方出现段错误,因为您试图从 Mat.data
指针本身的位置开始发送数据,而不是从它指向的内存位置开始发送数据。接收方出现段错误是因为没有 space 来存储 768 KiB 的数据(如果有的话)。
您可以先打包数据,但这需要额外的缓冲区。您最好的选择是简单地发送两条消息:
- 具有图像大小的一个,以便接收者可以准备一个适当大小的
Mat
对象;
- 一个与图像数据本身。
有时发送两条消息比将所有消息打包成一条消息更好。
typedef struct MyImage {
int w;
int h;
} image;
int blocksCount = 2;
int blocksLength[2] = {1, 1};
MPI_Datatype types[2] = {MPI_INT, MPI_INT};
MPI_Aint offsets[2];
MPI_Datatype custom_type;
offsets[0] = offsetof(image, w);
offsets[1] = offsetof(image, h);
MPI_Type_create_struct(blocksCount, blocksLength, offsets, types, &custom_type);
MPI_Type_commit(&custom_type);
if (rank == 0) {
Mat mat = imread("/home/user/image.jpg", CV_LOAD_IMAGE_COLOR);
image send;
send.w = mat.size().width;
send.h = mat.size().height;
// Send image dimensions
MPI_Send(&send, 1, custom_type, 1, 0, MPI_COMM_WORLD);
// Send image data
MPI_Send(mat.data, send.w*send.h*3, MPI_UNSIGNED_CHAR, 1, 0, MPI_COMM_WORLD);
}
if (rank == 1) {
image recv;
MPI_Status status;
// Receive image dimensions
MPI_Recv(&recv, 1, custom_type, 0, 0, MPI_COMM_WORLD, &status);
// Allocate image matrix
Mat mat(Size(recv.w, recv.h), CV_8UC3);
// Receive image data
MPI_Recv(mat.data, recv.w*recv.h*3, MPI_UNSIGNED_CHAR, 0, 0, MPI_COMM_WORLD, &status);
...
}
我想发送图像数据(unsigned char 数组)、宽度和高度从 0 级到 1 级。执行此操作的最佳方法是什么?我读过要在 MPI 中发送复杂的数据结构,我们可以使用打包数据或创建自己的数据类型。什么对我来说更好?
我试图通过创建一个新的数据类型来做到这一点。但我错了:Segmentation fault (signal 11)
。当我从我的结构中删除数组时,它就起作用了。那么发送这个数组有什么问题呢?
我的结构:
typedef struct MyImage {
int w;
int h;
unsigned char *data;
} image;
主要:
int main(int argc, char **argv) {
int size, rank;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
int blocksCount = 3;
int blocksLength[3] = {1, 1, 512 * 512 * 3};
// I also tried MPI_BYTE
MPI_Datatype types[3] = {MPI_INT, MPI_INT, MPI_UNSIGNED_CHAR};
MPI_Aint offsets[3];
MPI_Datatype custom_type;
offsets[0] = offsetof(image, w);
offsets[1] = offsetof(image, h);
offsets[3] = offsetof(image, data);
MPI_Type_create_struct(blocksCount, blocksLength, offsets, types, &custom_type);
MPI_Type_commit(&custom_type);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (rank == 0) {
Mat mat = imread("/home/user/image.jpg", CV_LOAD_IMAGE_COLOR);
image send;
send.w = mat.size().width;
send.h = mat.size().height;
send.data = mat.data;
MPI_Send(&send, 1, custom_type, 1, 0, MPI_COMM_WORLD);
}
if (rank == 1) {
image recv;
MPI_Status status;
MPI_Recv(&recv, 1, custom_type, 0, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
}
MPI_Type_free(&custom_type);
MPI_Finalize();
return 0;
}
发送方出现段错误,因为您试图从 Mat.data
指针本身的位置开始发送数据,而不是从它指向的内存位置开始发送数据。接收方出现段错误是因为没有 space 来存储 768 KiB 的数据(如果有的话)。
您可以先打包数据,但这需要额外的缓冲区。您最好的选择是简单地发送两条消息:
- 具有图像大小的一个,以便接收者可以准备一个适当大小的
Mat
对象; - 一个与图像数据本身。
有时发送两条消息比将所有消息打包成一条消息更好。
typedef struct MyImage {
int w;
int h;
} image;
int blocksCount = 2;
int blocksLength[2] = {1, 1};
MPI_Datatype types[2] = {MPI_INT, MPI_INT};
MPI_Aint offsets[2];
MPI_Datatype custom_type;
offsets[0] = offsetof(image, w);
offsets[1] = offsetof(image, h);
MPI_Type_create_struct(blocksCount, blocksLength, offsets, types, &custom_type);
MPI_Type_commit(&custom_type);
if (rank == 0) {
Mat mat = imread("/home/user/image.jpg", CV_LOAD_IMAGE_COLOR);
image send;
send.w = mat.size().width;
send.h = mat.size().height;
// Send image dimensions
MPI_Send(&send, 1, custom_type, 1, 0, MPI_COMM_WORLD);
// Send image data
MPI_Send(mat.data, send.w*send.h*3, MPI_UNSIGNED_CHAR, 1, 0, MPI_COMM_WORLD);
}
if (rank == 1) {
image recv;
MPI_Status status;
// Receive image dimensions
MPI_Recv(&recv, 1, custom_type, 0, 0, MPI_COMM_WORLD, &status);
// Allocate image matrix
Mat mat(Size(recv.w, recv.h), CV_8UC3);
// Receive image data
MPI_Recv(mat.data, recv.w*recv.h*3, MPI_UNSIGNED_CHAR, 0, 0, MPI_COMM_WORLD, &status);
...
}