3 回答

TA貢獻1816條經(jīng)驗 獲得超6個贊
耶利米是對的-MPI_Type_create_struct是前往此處的方法。
重要的是要記住,MPI是一個庫,而不是語言的內(nèi)置庫。因此它無法“看到”結(jié)構(gòu)將其自身序列化的樣子。因此,要發(fā)送復(fù)雜的數(shù)據(jù)類型,必須顯式定義其布局。在確實具有序列化支持的語言中,一組MPI包裝器可以方便地利用它。例如,mpi4py利用python的pickle透明地發(fā)送復(fù)雜的數(shù)據(jù)類型;但是在C語言中,您必須卷起袖子,自己動手做。
對于您的結(jié)構(gòu),它看起來像這樣:
#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;
}

TA貢獻2019條經(jīng)驗 獲得超9個贊
盡管喬納森·杜爾西(Jonathan Dursi)的回答是正確的,但它過于復(fù)雜。MPI提供了更簡單,通用性更小的類型構(gòu)造函數(shù),更適合您的問題。MPI_Type_create_struct僅當您具有不同的基本類型(例如int和float)時才需要。
對于您的示例,存在幾種更好的解決方案:
假設(shè)兩個整數(shù)在連續(xù)的內(nèi)存區(qū)域中對齊(即,就像整數(shù)數(shù)組一樣),則根本不需要派生的數(shù)據(jù)類型。只需發(fā)送/接收兩個具有type MPI_INT變量的地址的type元素car即可用作發(fā)送/接收緩沖區(qū):
MPI_Send(&send, 2, MPI_INT, dest, tag, MPI_COMM_WORLD);
MPI_Recv(&recv, 2, MPI_INT, src, tag, MPI_COMM_WORLD, &status);
如果要使用派生的數(shù)據(jù)類型(例如,出于可讀性或樂趣),則可以使用MPI_Type_contiguous與數(shù)組相對應(yīng)的數(shù)據(jù)類型:
MPI_Type_contiguous(2, MPI_INT, &mpi_car_type);
如果兩個整數(shù)的對齊方式不同(很可能不是這種情況,但這是與機器相關(guān)的,并且MPI實現(xiàn)存在于許多不同的平臺上),則可以使用MPI_Type_indexed_block:它接受一組位移數(shù)組(如MPI_Type_create_struct),但是只有一個舊類型參數(shù),每個塊的塊長按定義為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);
盡管其他解決方案在語義上是正確的,但它很難閱讀,并且可能會導(dǎo)致較大的性能損失。

TA貢獻1811條經(jīng)驗 獲得超5個贊
int MPI_Send(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm)
OpenMPI將發(fā)送count * sizeof(datatype)從開始的連續(xù)字節(jié),buf以允許發(fā)送類似int數(shù)組的內(nèi)容。例如,如果聲明一個10 int數(shù)組int arr[10],則可以使用
MPI_Send(arr, 10, MPI_INT, 1, 0, MPI_COMM_WORLD);
并收到類似的消息。由于buf是空指針,我們可以通過發(fā)送sizeof(my_struct)字節(jié)并在接收端將其強制轉(zhuǎn)換為結(jié)構(gòu)來濫用此結(jié)構(gòu)來發(fā)送結(jié)構(gòu)。這是一個例子:
#include "mpi.h"
#include <stdio.h>
typedef struct
{
char a;
int b;
short c;
} my_struct;
int main (int argc, char *argv[])
{
int numtasks, taskid;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &taskid);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
if (taskid == 0)
{
my_struct m;
m.a = '!';
m.b = 1234;
m.c = 5678;
MPI_Send(&m, sizeof(my_struct), MPI_CHAR, 1, 0, MPI_COMM_WORLD);
}
else
{
my_struct m;
MPI_Recv(&m, sizeof(my_struct), MPI_CHAR, 0, 0, MPI_COMM_WORLD,
MPI_STATUS_IGNORE);
printf("%c %d %d\n", m.a, m.b, m.c);
}
MPI_Finalize();
}
由于C數(shù)組是連續(xù)存儲數(shù)據(jù)的,所以我們甚至可以像構(gòu)造m數(shù)組一樣發(fā)送結(jié)構(gòu)數(shù)組。因此,如果您有一個my_struct m_array[10],則可以發(fā)送(并以類似方式接收)
MPI_Send(m_array, sizeof(my_struct) * 10, MPI_CHAR, 1, 0, MPI_COMM_WORLD);
- 3 回答
- 0 關(guān)注
- 666 瀏覽
添加回答
舉報