MPI,C,派生类型,向量结构?

时间:2022-10-08 13:51:20

I need to create an MPI derived type to represent a class in my program. The class is fairly straight forward, but large (about 75 data members**). All the data members are single values, 1D arrays, or 2D arrays. Here is an example:

我需要创建一个MPI派生类型来表示我的程序中的类。该课程相当简单,但规模很大(大约75个数据成员**)。所有数据成员都是单值,一维数组或二维数组。这是一个例子:

class RestartData {
  int dsr;
  double firea2sorgn;
  int ifwoody[NUM_PFT];
  double rootfrac[MAX_ROT_LAY][NUM_PFT];
  ....
  ....
}

I think that using the MPI_Type_struct is appropriate. (e.g. http://www.open-mpi.org/doc/v1.5/man3/MPI_Type_struct.3.php)

我认为使用MPI_Type_struct是合适的。 (例如http://www.open-mpi.org/doc/v1.5/man3/MPI_Type_struct.3.php)

And I more or less follow the example in this question: struct serialization in C and transfer over MPI, but I am not sure how to handle the 2D arrays. Can I make an MPI_Type_struct that contains several MPI_Type_vectors? I have been unable to find an example of creating an MPI_Type_struct containing 2D arrays. Am I on the right approach?

我或多或少地遵循这个问题中的示例:C中的结构序列化和通过MPI传输,但我不知道如何处理2D数组。我可以创建一个包含多个MPI_Type_vectors的MPI_Type_struct吗?我一直无法找到创建包含2D数组的MPI_Type_struct的示例。我是在正确的方法吗?

Thanks in advance.

提前致谢。


** I think I understand the possible problems with passing a single large message, but in this case, the message is passed infrequently, and at a natural synchronization point (slaves sending data back to the master when they are done crunching numbers)

**我认为我理解传递单个大型消息可能存在的问题,但在这种情况下,消息很少传递,并且在自然同步点(从属数据完成后将数据发送回主服务器)

2 个解决方案

#1


3  

Derived types in MPI can be freely constructed from other derived types and then used to further create other derived types.

MPI中的派生类型可以从其他派生类型*构造,然后用于进一步创建其他派生类型。

2D arrays, as long as they are contiguous in memory as in your case, are not that different from 1D arrays. When it comes to the rootfrac member, you could either create a contiguous datatype with MAX_ROOT_LAY * NUM_PFT elements of type MPI_DOUBLE or you could create a contiguous datatype (let's call it t_dbl_pft) with NUM_PFT elements of type MPI_DOUBLE and then use it to create another contiguous datatype with MAX_ROOT_LAY elements of type t_dbl_pft. Another option is to not create a datatype at all since the MPI structured type constructor takes a separate block length (i.e. number of elements) for each element of the structure.

2D数组,只要它们在内存中是连续的,就像你的情况一样,与1D数组没有什么不同。当涉及到rootfrac成员时,您可以使用MPI_DOUBLE类型的MAX_ROOT_LAY * NUM_PFT元素创建连续数据类型,也可以使用类型为MPI_DOUBLE的NUM_PFT元素创建连续数据类型(让我们称之为t_dbl_pft),然后使用它创建另一个连续的数据类型数据类型,包含类型为t_dbl_pft的MAX_ROOT_LAY个元素。另一个选择是根本不创建数据类型,因为MPI结构类型构造函数为结构的每个元素采用单独的块长度(即元素的数量)。

For example, the following type describes the data members that you've shown:

例如,以下类型描述了您显示的数据成员:

#include <cstddef> // for offsetof

MPI_Type t_1d;
MPI_Type_contiguous(NUM_PFT, MPI_DOUBLE, &t_1d);
// No need to commit - this type is not used for communication

MPI_Type t_restart;
int counts[4] = { 1, 1, NUM_PFT, MAX_ROT_LAY };
MPI_Type types[4] = { MPI_INT, MPI_DOUBLE, MPI_INT, t_1d };
MPI_Aint displs[4] = {
   offsetof(RestartData, dsr),
   offsetof(RestartData, firea2sorgn),
   offsetof(RestartData, ifwoody),
   offsetof(RestartData, rootfrac),
};
MPI_Type_create_struct(4, counts, displs, types, &t_restart);
MPI_Type_commit(&t_restart);

// The 1D type is no longer needed
MPI_Type_free(&t_1d);

Note that you have to either create the MPI datatype inside a member function of RestartData or declare the routine where the type is created as friend to the class so that it could access the private and protected data members. Also note that offsetof only works with POD (plain old data) classes, e.g. no fancy constructors and members of types like std::string.

请注意,您必须在RestartData的成员函数内创建MPI数据类型,或者声明将类型创建为类的朋友的例程,以便它可以访问私有和受保护的数据成员。还要注意,offsetof仅适用于POD(普通旧数据)类,例如没有花哨的构造函数和std :: string类型的成员。

#2


1  

The easiest way to go is to just treat the whole object as a big buffer:

最简单的方法是将整个对象视为一个大缓冲区:

MPI_Datatype datatype;

MPI_Type_contiguous(sizeof(RestartData), MPI_BYTE, &datatype);
MPI_Type_commit(&datatype);

I don't see the benefit of telling MPI about the internal structure of your class.

我没有看到告诉MPI关于你班级内部结构的好处。

Alternatively a 2D array is an array of 1D arrays. So (I imagine) you could use one call to MPI_Type_contiguous per array dimension to build up the array datatype.

或者,2D阵列是1D阵列的阵列。所以(我想)你可以使用每个数组维度调用MPI_Type_contiguous来构建数组数据类型。

#1


3  

Derived types in MPI can be freely constructed from other derived types and then used to further create other derived types.

MPI中的派生类型可以从其他派生类型*构造,然后用于进一步创建其他派生类型。

2D arrays, as long as they are contiguous in memory as in your case, are not that different from 1D arrays. When it comes to the rootfrac member, you could either create a contiguous datatype with MAX_ROOT_LAY * NUM_PFT elements of type MPI_DOUBLE or you could create a contiguous datatype (let's call it t_dbl_pft) with NUM_PFT elements of type MPI_DOUBLE and then use it to create another contiguous datatype with MAX_ROOT_LAY elements of type t_dbl_pft. Another option is to not create a datatype at all since the MPI structured type constructor takes a separate block length (i.e. number of elements) for each element of the structure.

2D数组,只要它们在内存中是连续的,就像你的情况一样,与1D数组没有什么不同。当涉及到rootfrac成员时,您可以使用MPI_DOUBLE类型的MAX_ROOT_LAY * NUM_PFT元素创建连续数据类型,也可以使用类型为MPI_DOUBLE的NUM_PFT元素创建连续数据类型(让我们称之为t_dbl_pft),然后使用它创建另一个连续的数据类型数据类型,包含类型为t_dbl_pft的MAX_ROOT_LAY个元素。另一个选择是根本不创建数据类型,因为MPI结构类型构造函数为结构的每个元素采用单独的块长度(即元素的数量)。

For example, the following type describes the data members that you've shown:

例如,以下类型描述了您显示的数据成员:

#include <cstddef> // for offsetof

MPI_Type t_1d;
MPI_Type_contiguous(NUM_PFT, MPI_DOUBLE, &t_1d);
// No need to commit - this type is not used for communication

MPI_Type t_restart;
int counts[4] = { 1, 1, NUM_PFT, MAX_ROT_LAY };
MPI_Type types[4] = { MPI_INT, MPI_DOUBLE, MPI_INT, t_1d };
MPI_Aint displs[4] = {
   offsetof(RestartData, dsr),
   offsetof(RestartData, firea2sorgn),
   offsetof(RestartData, ifwoody),
   offsetof(RestartData, rootfrac),
};
MPI_Type_create_struct(4, counts, displs, types, &t_restart);
MPI_Type_commit(&t_restart);

// The 1D type is no longer needed
MPI_Type_free(&t_1d);

Note that you have to either create the MPI datatype inside a member function of RestartData or declare the routine where the type is created as friend to the class so that it could access the private and protected data members. Also note that offsetof only works with POD (plain old data) classes, e.g. no fancy constructors and members of types like std::string.

请注意,您必须在RestartData的成员函数内创建MPI数据类型,或者声明将类型创建为类的朋友的例程,以便它可以访问私有和受保护的数据成员。还要注意,offsetof仅适用于POD(普通旧数据)类,例如没有花哨的构造函数和std :: string类型的成员。

#2


1  

The easiest way to go is to just treat the whole object as a big buffer:

最简单的方法是将整个对象视为一个大缓冲区:

MPI_Datatype datatype;

MPI_Type_contiguous(sizeof(RestartData), MPI_BYTE, &datatype);
MPI_Type_commit(&datatype);

I don't see the benefit of telling MPI about the internal structure of your class.

我没有看到告诉MPI关于你班级内部结构的好处。

Alternatively a 2D array is an array of 1D arrays. So (I imagine) you could use one call to MPI_Type_contiguous per array dimension to build up the array datatype.

或者,2D阵列是1D阵列的阵列。所以(我想)你可以使用每个数组维度调用MPI_Type_contiguous来构建数组数据类型。