用于复杂对象的MPI共享内存

MPI Shared Memory for Complex Object

本文关键字:共享 内存 MPI 复杂 对象 用于      更新时间:2023-10-16

我有一个大规模的代码,它在许多CPU核心上运行,可能跨越许多计算节点。该代码使用C++编写,并使用OpenMPI进行了并行处理。

我的代码有一个非常大的对象(大约10GB的RAM使用量),每个MPI进程都从中读取。这个对象偶尔会更新(可以通过一个进程完成,只需读取一个数据文件)。

到目前为止,我所做的是为每个MPI进程提供一个该对象的副本;但这意味着我的RAM严重受限,无法使用节点的全部CPU功率。因此,我一直在阅读MPI3规范中关于共享内存的内容。

我的问题是:在MPI进程之间共享复杂对象的最佳方式是什么?在我发现的所有例子中,MPI共享内存窗口都是创建的,用于交换简单的数据结构(浮点、int数组等)。我的全局对象是一个自定义类类型,包括许多成员变量,其中一些是指针,许多是其他复杂的类类型。因此,我觉得我不能只调用MPI_Win_allocate_shared并传递复杂对象的地址,尤其是因为我想共享关于成员变量的所有信息(特别是,我想共享指针类型成员变量的底层值,即在MPI进程之间共享"深度副本",每个进程中的所有虚拟内存地址都是正确的)。

有可能用MPI共享内存实现这种"深度共享"吗?如果有,是否有这样做的"最佳实践"?或者另一个库(例如boost interprocess)会让这对我来说更可行/更简单吗?

附言:如果我不能找到一个好的解决方案,我将采用MPI+Ppthreads混合方法,在这种方法中,我知道我可以很容易地在每个具有pthreads的节点上拥有这个全局对象。但我真的希望找到一个优雅的MPI专用解决方案。

如果您跨越机器边界(并且在许多机器上使用节点),那么没有任何简单的方法可以实现您的目标。如果你只使用Windows或Linux机器(而不是混合使用它们),你可以尝试破解它,例如将一些共享资源附加到虚拟内存(使用系统API以高效的方式实现)。另一种方法是为大型对象创建自定义序列化/反序列化代码,然后将其作为二进制数组存储在内存中(在同一台机器上的进程之间共享)。如果您试图只存储"内存转储",那么问题是大小端序。如果您使用专用的MPIapi,那么所有的endian(和数据表示问题)都会得到适当的支持。目前我不确定PVM是否更好地支持这种场景,但在MPI的情况下,我可以从在同一台机器上直接使用VM开始(仅在进程之间共享一些访问密钥)。。。

附加答案1:

在一台机器上,我认为它应该很简单(你可能使用Windows,所以我现在将专注于这个平台)。在这种情况下,Endian问题和数据对齐并不重要,因为我假设您使用相同的选项编译所有的东西(并在相同的硬件上使用)。实现目标的最简单方法是将一个命名正确的文件映射到虚拟内存(在为不同对象创建许多映射之前,名称目前并不重要——在这种情况下,您需要一些命名模式来保持一致性)。例如,样品就在这里。

在创建虚拟内存之后,将所有对象数据放置在那里(使用老式的memcpy或所谓的放置构造函数)。当所有数据都已在虚拟内存中可用时,只需将带有一些附加属性的文件名发送到同一机器上的所有进程/节点即可。在虚拟内存空间的开头,如果有多个对象,您可以放置一些带有指向对象的指针的数组(例如,带有分配地址delta),以便轻松链接所有相关对象(在这种情况下,vm中的第一个On元素应该包含该数组中的elem数,这只是一个想法)。您可以在每个进程上将虚拟内存映射到相同的虚拟地址,这样,如果您对指针根本不感兴趣,就不必管理指针:)在这种情况下,不需要任何带有指针的数组!

使用虚拟内存的另一个好处是它优化了内存页面的使用,因此在您有如此大的数据对象的情况下,它不会吞噬10GB的内存。

顺便说一句:Windows支持与一些打开部分直接共享内存页。在CPP中,您有这样的支持。