gpt4 book ai didi

c - MPI 派生类型发送

转载 作者:太空宇宙 更新时间:2023-11-04 02:04:11 26 4
gpt4 key购买 nike

我尝试将派生类型发送给处理器。该类型包含来自其他派生类型的对象。我从 Examples: Struct Derived Data Type 开始这个例子.我添加我的代码。代码有点长,但两种类型基本相同。我有 Part 对象,它也有一个 Particle 对象,我想发送 Part。我得到的结果在代码之后。

#include "mpi.h"
#include <stdio.h>
#define NELEM 25

main(int argc, char *argv[]) {
int numtasks, rank, source=0, dest, tag=1, i;

typedef struct {
float x, y, z;
float velocity;
int n, type;
} Particle;

// Another struct to send
typedef struct {
char character;
Particle part ;
} Part ;

MPI_Request send_req;
MPI_Status stat;


MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);

// Particle type
Particle particles;
MPI_Datatype particletype, oldtypes[2];
int blockcounts[2];
MPI_Aint offsets[2], extent;

offsets[0] = 0;
oldtypes[0] = MPI_FLOAT;
blockcounts[0] = 4;
MPI_Type_extent(MPI_FLOAT, &extent);
offsets[1] = 4 * extent;
oldtypes[1] = MPI_INT;
blockcounts[1] = 2;

MPI_Type_struct(2, blockcounts, offsets, oldtypes, &particletype);
MPI_Type_commit(&particletype);


// Part type
Part party , party_received;
MPI_Datatype part_type,oldtype2[2];
int blockcount2[2];
MPI_Aint offset2[2],extent2;

offset2[0] = 0;
oldtype2[0] = MPI_CHAR ;
blockcount2[0] = 1 ;

MPI_Type_extent(particletype,&extent);
offset2[1] = extent ;
oldtype2[1] = particletype ;
blockcount2[1] = 1 ;

MPI_Type_struct(2,blockcount2,offset2,oldtype2,&part_type);
MPI_Type_commit(&part_type);


party.character= 'a';

if (rank == 0) {

particles.x = 1 * 1.0;
particles.y = 1 * -1.0;
particles.z = 1 * 1.0;
particles.velocity = 0.25;
particles.n = 1;
particles.type = 1 % 2;

party.part = particles;

printf("Derived data type sending, character: %c \n",party.character);
MPI_Isend(&party,1,part_type,1,tag,MPI_COMM_WORLD,&send_req);
printf("particles sent %f %f %f %f %d %d \n",
party.part.x,party.part.y,party.part.z,
party.part.velocity,party.part.n,party.part.type);
}
if(rank == 1) {
MPI_Recv(&party_received, 1, part_type, 0, tag, MPI_COMM_WORLD, &stat);
printf("derived part type received character %c \n",party_received.character) ;
printf("particles %f %f %f %f %d %d \n",
party_received.part.x,party_received.part.y,party_received.part.z,
party_received.part.velocity,party_received.part.n,party_received.part.type);
}
MPI_Type_free(&particletype);
MPI_Finalize();
}

结果每次都不同。最后一个是:

Derived data type sending, character: a 
particles sent 1.000000 -1.000000 1.000000 0.250000 1 1
derived part type received character a
particles 0.000000 -2686527813451776.000000 0.000000 0.000000 1 1

虽然 character 是真的,为什么 Particle 对象不是?我该如何纠正它?

最佳答案

您错误地计算了偏移量。

offset2[0] = 0;
oldtype2[0] = MPI_CHAR ;
blockcount2[0] = 1 ;

MPI_Type_extent(particletype,&extent);
offset2[1] = extent ; <--- WRONG
oldtype2[1] = particletype ;
blockcount2[1] = 1 ;

这里的偏移量不是结构体第二个成员的范围。它是第一个的范围 + 可能是一些填充(在你的情况下 - 3 个字节的填充)。

为了防止以后出现类似的错误,我建议您改用 offsetof():

#include <stddef.h>

offset[0] = offsetof(Part, character);
offset[1] = offsetof(Part, part);

使用范围计算偏移量在概念上是错误的,因为不能保证结构内部使用的填充与范围相匹配。一个简单的例子:MPI_CHAR 在大多数系统上都有 1 个字节的范围,但是如果你有一个像 struct { char a; 这样的结构。诠释乙; },因为对齐的要求,ab之间会有3个字节的填充。这同样适用于您的 Part 结构 - 由于 Particle 的第一个成员是 float ,因此 part 成员使用填充对齐。

如果您的系统没有offsetof,您可以将其替换为MPI_Get_address:

Part party;
MPI_Aint base, member_offset;

MPI_Get_address(&party, &base);

MPI_Get_address(&party.character, &member_offset);
offset[0] = member_offset - base;

MPI_Get_address(&party.part, &member_offset);
offset[1] = member_offset - base;

关于c - MPI 派生类型发送,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22709015/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com