在MPI上创建结构和联合

时间:2013-10-28 14:16:46

标签: c struct mpi unions

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);

我接近正确的代码吗?

1 个答案:

答案 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中分配它的内存。如果这不可行,你将不得不做更多的内存杂耍,以便将你的字符串传递给其他进程,就像使用任何可变大小的数组一样。