结构数组上 MPI send/recv 的正确方法
Correct method of MPI send/recv on an array of structs
我一直在用树莓派建立一个四节点的 mpi 集群。据我所知,我要解决最后一个主要问题,那就是如何将一组结构从每个工人发送到经理。我已将代码裁剪到下面,但这可能需要尝试几次,因为我可能裁剪得太多了。尽管如此,我仍然遇到同样的错误(一个段错误,说地址未映射),但是如果有一点倒退和第四次,我很抱歉。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mpi.h>
struct ticknrank
{
char * ticker;
int errors;
int rank;
};
int main() //Designed for one master, three slaves
{
// i am under the impression the problem lies somewhere in this beginning section, before the commit.
int my_id;
MPI_Init(NULL,NULL);
MPI_Comm_rank(MPI_COMM_WORLD, &my_id);
MPI_Status status;
MPI_Datatype types[3] = {MPI_CHAR,MPI_INT,MPI_INT};
MPI_Datatype MPI_ticknrank, MPI_tmp;
int blocklengths[3] ={8,1,1};
MPI_Aint offsets[3];
offsets[0] = offsetof(struct ticknrank,ticker);
offsets[1] = offsetof(struct ticknrank,errors);
offsets[2]= offsetof(struct ticknrank,rank);
MPI_Aint lb, extent;
MPI_Type_create_struct(3,blocklengths, offsets, types, &MPI_tmp);
MPI_Type_get_extent(MPI_tmp, &lb, &extent);
MPI_Type_create_resized(MPI_tmp, lb, extent, &MPI_ticknrank);
MPI_Type_commit(&MPI_ticknrank);
// NOTE: sizeof(ticknrank) = 12, while MPI_Type_size(ticknrank) = 16. Not sure what to do about that.
if(my_id == 0) // meaning this process is a host job
{
//NOTE: NodethrRes and fou can be ommitted, I was just lazy and didn't wanna delete them
//on my cluster.
int length = 2;
struct ticknrank * NodeTwoRes = (struct ticknrank *)malloc(length * sizeof(struct ticknrank));
struct ticknrank * NodeThrRes = (struct ticknrank *)malloc(length * sizeof(struct ticknrank));
struct ticknrank * NodeFouRes = (struct ticknrank *)malloc(length * sizeof(struct ticknrank));
MPI_Recv(NodeTwoRes, length, MPI_ticknrank,1,MPI_ANY_TAG, MPI_COMM_WORLD, &status);
MPI_Recv(NodeThrRes, length, MPI_ticknrank,2,MPI_ANY_TAG, MPI_COMM_WORLD, &status);
MPI_Recv(NodeFouRes, length, MPI_ticknrank,3,MPI_ANY_TAG, MPI_COMM_WORLD, &status);
printf("%s\n", NodeTwoRes[0].ticker);
}
else
{
int myLen = 2;
struct ticknrank * results = malloc(myLen * sizeof(struct ticknrank));
results[0].ticker = strdup("FIRST");
results[0].rank = 4;
results[0].errors = 7;
results[1].ticker = strdup("SECON");
results[1].rank = 3;
results[1].errors = 15;
MPI_Send(results,myLen,MPI_ticknrank,0,1,MPI_COMM_WORLD);
}
MPI_Type_free(&MPI_ticknrank);
MPI_Finalize();
return 0;
}
C
结构是一个 char * ticker
(如果你是 运行 32 位,它是 4 个字节),但是派生的数据类型是 char ticker[8]
,它是确实是 8 个字节。
如果要一次发送多个struct ticknrank
,那么数据应该在连续的内存中,这意味着从char * ticker
移动到char ticker[8]
,并替换strdup()
和 strcpy()
(由您来确保没有缓冲区溢出)。
我一直在用树莓派建立一个四节点的 mpi 集群。据我所知,我要解决最后一个主要问题,那就是如何将一组结构从每个工人发送到经理。我已将代码裁剪到下面,但这可能需要尝试几次,因为我可能裁剪得太多了。尽管如此,我仍然遇到同样的错误(一个段错误,说地址未映射),但是如果有一点倒退和第四次,我很抱歉。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mpi.h>
struct ticknrank
{
char * ticker;
int errors;
int rank;
};
int main() //Designed for one master, three slaves
{
// i am under the impression the problem lies somewhere in this beginning section, before the commit.
int my_id;
MPI_Init(NULL,NULL);
MPI_Comm_rank(MPI_COMM_WORLD, &my_id);
MPI_Status status;
MPI_Datatype types[3] = {MPI_CHAR,MPI_INT,MPI_INT};
MPI_Datatype MPI_ticknrank, MPI_tmp;
int blocklengths[3] ={8,1,1};
MPI_Aint offsets[3];
offsets[0] = offsetof(struct ticknrank,ticker);
offsets[1] = offsetof(struct ticknrank,errors);
offsets[2]= offsetof(struct ticknrank,rank);
MPI_Aint lb, extent;
MPI_Type_create_struct(3,blocklengths, offsets, types, &MPI_tmp);
MPI_Type_get_extent(MPI_tmp, &lb, &extent);
MPI_Type_create_resized(MPI_tmp, lb, extent, &MPI_ticknrank);
MPI_Type_commit(&MPI_ticknrank);
// NOTE: sizeof(ticknrank) = 12, while MPI_Type_size(ticknrank) = 16. Not sure what to do about that.
if(my_id == 0) // meaning this process is a host job
{
//NOTE: NodethrRes and fou can be ommitted, I was just lazy and didn't wanna delete them
//on my cluster.
int length = 2;
struct ticknrank * NodeTwoRes = (struct ticknrank *)malloc(length * sizeof(struct ticknrank));
struct ticknrank * NodeThrRes = (struct ticknrank *)malloc(length * sizeof(struct ticknrank));
struct ticknrank * NodeFouRes = (struct ticknrank *)malloc(length * sizeof(struct ticknrank));
MPI_Recv(NodeTwoRes, length, MPI_ticknrank,1,MPI_ANY_TAG, MPI_COMM_WORLD, &status);
MPI_Recv(NodeThrRes, length, MPI_ticknrank,2,MPI_ANY_TAG, MPI_COMM_WORLD, &status);
MPI_Recv(NodeFouRes, length, MPI_ticknrank,3,MPI_ANY_TAG, MPI_COMM_WORLD, &status);
printf("%s\n", NodeTwoRes[0].ticker);
}
else
{
int myLen = 2;
struct ticknrank * results = malloc(myLen * sizeof(struct ticknrank));
results[0].ticker = strdup("FIRST");
results[0].rank = 4;
results[0].errors = 7;
results[1].ticker = strdup("SECON");
results[1].rank = 3;
results[1].errors = 15;
MPI_Send(results,myLen,MPI_ticknrank,0,1,MPI_COMM_WORLD);
}
MPI_Type_free(&MPI_ticknrank);
MPI_Finalize();
return 0;
}
C
结构是一个 char * ticker
(如果你是 运行 32 位,它是 4 个字节),但是派生的数据类型是 char ticker[8]
,它是确实是 8 个字节。
如果要一次发送多个struct ticknrank
,那么数据应该在连续的内存中,这意味着从char * ticker
移动到char ticker[8]
,并替换strdup()
和 strcpy()
(由您来确保没有缓冲区溢出)。