我已经定义了一个自定义结构,并希望使用MPI_Bsend(或MPI_Send)将其发送到另一个MPI进程.
这是我的结构:
struct car{
int shifts;
int topSpeed;
}myCar;
Run Code Online (Sandbox Code Playgroud)
但是,除了原始类型之外,MPI似乎不支持复杂数据类型的直接"传输",如上面的结构.我听说我可能不得不使用"序列化".我该如何处理它并将'myCar'发送到进程5?
Jon*_*rsi 59
Jeremiah是对的 - MPI_Type_create_struct是去的地方.
重要的是要记住MPI是一个没有内置于该语言中的库; 所以它无法"看到"结构本身序列化的样子.因此,要发送复杂的数据类型,您必须明确定义其布局.在一种对序列化有本机支持的语言中,一组MPI包装器可以巧妙地利用它; 例如,mpi4py利用python的pickle来透明地发送复杂的数据类型; 但在C中,你必须卷起袖子自己动手.
对于您的结构,它看起来像这样:
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#include <stddef.h>
typedef struct car_s {
int shifts;
int topSpeed;
} car;
int main(int argc, char **argv) {
const int tag = 13;
int size, rank;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
if (size < 2) {
fprintf(stderr,"Requires at least two processes.\n");
exit(-1);
}
/* create a type for struct car */
const int nitems=2;
int blocklengths[2] = {1,1};
MPI_Datatype types[2] = {MPI_INT, MPI_INT};
MPI_Datatype mpi_car_type;
MPI_Aint offsets[2];
offsets[0] = offsetof(car, shifts);
offsets[1] = offsetof(car, topSpeed);
MPI_Type_create_struct(nitems, blocklengths, offsets, types, &mpi_car_type);
MPI_Type_commit(&mpi_car_type);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (rank == 0) {
car send;
send.shifts = 4;
send.topSpeed = 100;
const int dest = 1;
MPI_Send(&send, 1, mpi_car_type, dest, tag, MPI_COMM_WORLD);
printf("Rank %d: sent structure car\n", rank);
}
if (rank == 1) {
MPI_Status status;
const int src=0;
car recv;
MPI_Recv(&recv, 1, mpi_car_type, src, tag, MPI_COMM_WORLD, &status);
printf("Rank %d: Received: shifts = %d topSpeed = %d\n", rank,
recv.shifts, recv.topSpeed);
}
MPI_Type_free(&mpi_car_type);
MPI_Finalize();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
mor*_*ort 13
虽然Jonathan Dursi的答案是正确的,但它过于复杂了.MPI提供更简单,更不通用的类型构造函数,更适合您的问题.MPI_Type_create_struct当你有不同的基类型时(例如,int和float),只需要它.
在您的示例中,存在几种更好的解决方案
假设两个整数在连续的内存区域中对齐(即,像整数数组一样),则根本不需要派生数据类型.只需发送/接收两个类型的元素,MPI_INT其中包含car要用作发送/接收缓冲区的类型变量的地址:
MPI_Send(&send, 2, MPI_INT, dest, tag, MPI_COMM_WORLD);
MPI_Recv(&recv, 2, MPI_INT, src, tag, MPI_COMM_WORLD, &status);
Run Code Online (Sandbox Code Playgroud)如果要使用派生数据类型(例如,为了可读性或它的乐趣),您可以使用MPI_Type_contiguous与数组相对应的数据类型:
MPI_Type_contiguous(2, MPI_INT, &mpi_car_type);
Run Code Online (Sandbox Code Playgroud)如果两个整数的排列方式不同(很可能不是这种情况,但它依赖于机器并且MPI实现存在于许多不同的平台上),您可以使用MPI_Type_indexed_block:它需要一个位移数组(如MPI_Type_create_struct),但只有一个旧类型根据定义,每个块的参数和块长度为1:
MPI_Aint offsets[2];
offsets[0] = offsetof(car, shifts) ; //most likely going to be 0
offsets[1] = offsetof(car, topSpeed);
MPI_Type_indexed_block(2, offsets, MPI_INT);
Run Code Online (Sandbox Code Playgroud)虽然另一种解决方案在语义上是正确的,但是阅读起来要困难得多,并且可能会导致很大的性能损失.
| 归档时间: |
|
| 查看次数: |
28357 次 |
| 最近记录: |