EDITED: 感谢您以前的帮助。我真的很感激。
我应该从* list中删除指针吗? 为了使用指针创建atributo和estrucura,它也会成为一个问题吗?
union atributo{
int valor1;
char valor2[tamChar];
float valor3;
};
struct estructura{
int tipo[tamEstruct]; //Here i will have an array with the types of the union
union atributo *list[tamEstruct];
};
union atributo *atributos;
struct estructura *estructuras;
estructuras = malloc (sizeof(struct estructura) * (cantEstruct) );
MPI_Datatype atributo_MPI;
MPI_Datatype type[1] = { MPI_BYTE };
int blocklen[1] = { tamChar }; // the largest element is the chat
MPI_Aint disp[1];
disp[0]= atributos[0]; // the begin of the union
MPI_Datatype estructura_MPI;
MPI_Datatype type[2] = { MPI_INT, atributo_MPI };
int blocklen[2] = { tamEstruct, tamEstruct};
MPI_Aint disp2[2];
disp2[0]= offsetof(atributos, tipo);
disp2[1]= offsetof(atributos, list);
我接近正确的代码吗?
答案 0 :(得分:1)
这段代码有几个问题。
首先,结构和联盟在这方面非常不同。一个struct包含列出的每个元素,在内存中一个接一个地排列。另一方面,union与其最大元素一样大,并且它的所有成员共享相同的内存空间(就像它们是结构的唯一成员一样)。这意味着您无法将联合包装到MPI_Struct
中,因为每个成员的偏移实际上都是0。
有两种方法可以解决一系列工会的问题:
MPI_BYTE
的数组发送。这很简单,但如果您的进程不共享相同的数据表示(例如,它们的整数在字节顺序上不同),则会导致数据损坏。MPI_Pack()
逐个打包值。这是类型安全的,但更复杂,它将导致数据的内存中副本。请注意,在任何一种情况下,接收过程都需要知道它收到了什么值(即,它是否接收了3个联合,是3个整数,还是2个整数和浮点数等)。如果你使用工会,你也必须发送这些信息。
您可能需要考虑一种更棘手的方法:根据枚举值的有效性对枚举进行分组,并发送一个消息,其中类似的枚举彼此相邻(例如,包含{{1的数组的消息) s,然后是MPI_INT
s的数组,依此类推)。通过巧妙使用派生的MPI数据类型,您可以保持类型安全,避免内存中复制,和避免发送多条消息。
第二:永远不要在MPI进程之间发送指针!很容易将MPI_FLOAT
视为char*
的数组,但事实并非如此。它只是一个内存地址,对你发送它的进程没有意义,即使它发生了,你实际上并没有发送它指向的数据。如果char
是一个具有相当短的最大长度的字符串,我建议将其声明为valor2
,以便在实际的struct / union中分配它的内存。如果这不可行,你将不得不做更多的内存杂耍,以便将你的字符串传递给其他进程,就像使用任何可变大小的数组一样。