如果我不必关心异构系统上的可移植性(字节序...):
为什么不使用 MPI_BYTE 进行所有通信?
特别是对于集体以及在处理组合数据类型时,这将使生活变得更加轻松。
编辑:我刚刚找到MPI 和 C structs。答案适用于我的问题。
如果我不必关心异构系统上的可移植性(字节序...):
为什么不使用 MPI_BYTE 进行所有通信?
特别是对于集体以及在处理组合数据类型时,这将使生活变得更加轻松。
编辑:我刚刚找到MPI 和 C structs。答案适用于我的问题。
好的,扩展我的尖刻评论的答案:
...出于同样的原因,我们不使用字节进行所有计算。在处理现代计算机程序中遇到的那种复杂性时,数据类型是一个巨大的帮助。为了支持这一断言,我引用了它们在汇编语言级别以上的所有编程语言中的存在,但即使在该级别,也存在数据类型的痕迹。
MPI 最常用的领域中的主要语言,即 Fortran、C 和 C++,具有与 MPI 中定义的数据类型密切对应的数据类型。当然,因果链在另一个方向上起作用,MPI 有这些类型,因为那些语言有。所有这些语言都允许程序员定义由更基本的数据类型组成的更多数据类型,再次帮助处理解决计算机难题的复杂性;MPI 也支持创建派生类型。
我不同意您的结论,即仅处理字节会使(MPI)编程更容易,它会使我的编程更加困难。如果我想从一个进程向另一个进程发送一条包含 24 个整数的消息,我想发送一个整数类型且长度为 24 的消息,我不想摆弄将其转换为多个字节。
以下是使用类型发送 3 维 NxNxN 数组切片的方法:
double array[N][N][N];
/* ... */
MPI_Datatype xslice, yslice, zslice;
int starts[3] = {0,N-2,0};
int sizes[3] = {N,N,N};
int subsizes[3] = {N,2,N};
MPI_Type_create_subarray(3, sizes, subsizes, starts, MPI_ORDER_C, MPI_DOUBLE, &yslice);
MPI_Type_commit(&yslice);
/* ... */
MPI_Send(&(array[0][0][0]), 1, yslice, neigh, ytag, MPI_COMM_WORLD);
MPI_BYTE
仅使用而不使用其他类型构造函数的更简单、无需键入的方法是什么?
所有高性能计算最终都归结为理解内存和数据布局,而使用更高级别的抽象有助于实现这一点。
如果您遇到问题MPI_Type_create_struct
,那么您来对地方了(或其中之一)。如果你来找人同意你的观点,是的,学习新东西太难而且不值得,你可能来错地方了。
编辑添加:。我同意在 C 和 Fortran 中,对于序列化(不仅仅是 MPI)来说,结构是一种痛苦的处理方式,为此我将其归咎于它们不可原谅的缺乏任何形式的甚至是基本的内省。要描述它们,您必须重申它们的类型和计数,这违反了 DRY 原则。到处都是一团糟,而且可能有不止一个代码只使用 sizeof(struct foo) MPI_BYTEs 来描述它们。但这是一个失败的具体例子。
现在您已正确发送和接收这些内容,您决定使用 MPI-IO(或就此而言,使用 HDF5 或 NetCDF 或...)将它们保存到文件中。您使用与它们通信相同的方法来描述它们,当然,作为 sizeof(struct foo) 字节。
然而,C 几乎没有告诉你这些结构是如何布局的。允许编译器对布局做各种事情,特别是插入填充。如果所有任务都运行使用相同编译器和标志在相同类型的机器上编译的相同代码,这通常不是通信问题。
但是现在,当您不可避免地使用相同的代码加载该文件但使用不同的编译器编译,或者甚至使用相同的编译器但使用不同的标志时,所有的赌注都没有了。数据布局可能不同,导致垃圾值 - 或者填充量可能不同,导致您读取文件末尾。
您可以通过不同地描述文件 I/O 和通信的数据来解决这个问题,但现在很难说这会使事情变得更简单。您最好一开始就正确描述数据。