我有一个大规模的代码,可以运行在许多CPU核心上,可能跨越许多计算节点。代码使用C ++编写,并与OpenMPI并行化。
我的代码有一个非常大的对象(~10GB RAM使用率),可以从每个MPI进程读取。此对象偶尔更新(可以通过单个进程完成,只需读入数据文件)。
到目前为止,我所做的是为每个MPI流程提供此对象的副本;但这意味着我严重限制了RAM,并且不能使用我的节点的全部CPU功率。所以,我一直在阅读MPI 3规范中的共享内存。
我的问题是:在MPI流程中共享复杂对象的最佳方法是什么?在我发现的所有示例中,创建了MPI共享内存窗口并用于交换简单的数据结构(浮点数,整数数组等)。我的全局对象是一个自定义类类型,它包含许多成员变量,其中一些是指针,其中许多是其他复杂的类类型。因此,我觉得我不能只调用MPI_Win_allocate_shared
并传递我的复杂对象的地址,特别是因为我想分享有关成员变量的所有信息(特别是,我想要共享指针类型成员变量的基础值 - 即在MPI进程中共享"深层复制"在每个进程中所有虚拟内存地址都正确。)
是否有可能实现这一目标"深度分享"与MPI共享内存,如果是这样,是否有最佳实践"这样做?或者另一个库(例如boost interprocess)会让我更可行/更直接吗?
P.S。如果我无法找到一个好的解决方案,我将采用混合MPI + pthreads方法,我知道我可以轻松地在每个节点上使用pthreads获得这个全局对象。但我真的希望找到一个优雅的MPI解决方案。
答案 0 :(得分:1)
如果跨越机器边界(并且在许多机器上使用节点),没有任何简单的方法可以实现您的目标。 如果您只使用Windows或Linux机器(不混合它们),您可以尝试以某种方式破解它,例如将一些共享资源附加到虚拟内存(使用系统API以高效方式执行)。其他方法可能是为大对象创建自定义序列化/反序列化代码,而不是将其作为二进制数组存储在内存中(在同一台机器上的进程之间共享)。如果您尝试仅存储“内存转储”,则问题是大/小端。如果你使用专用的MPI api,肯定会正确支持所有端序(和数据显示问题)。 目前我不确定PVM是否更好地支持这种情况,但是在MPI的情况下,我可以从在同一台机器上直接使用VM开始(仅在进程之间共享一些访问密钥)......
补充答案1:
在一台机器上,我认为应该很简单(你可能使用Windows,所以我现在将专注于这个平台)。在这种情况下,Endian问题和数据对齐并不重要,因为我假设您使用相同的选项编译所有东西(并在相同的硬件上使用)。实现目标的最简单方法是将虚拟内存映射到一个正确命名的文件(在您为不同对象创建多个映射之前,名称无关紧要 - 在这种情况下,您需要一些命名模式以保持一致性)。 Sample is here for instance.
创建虚拟内存后,将所有对象数据放在那里(使用旧学校memcpy或只是所谓的放置构造函数)。当所有数据都已在虚拟内存中可用时,只需将具有一些附加属性的文件名发送到同一台机器上的所有进程/节点。在虚拟内存空间的开头,您可以放置一些带有指向对象的数组(例如,使用分配地址增量),以便在有多个对象时轻松链接所有相关对象(在这种情况下,vm中的第一个元素)应该包含这种数组中的元素数量 - 这只是一个想法。您可以将虚拟内存映射到每个进程的相同虚拟地址,这样如果您根本不感兴趣,则无需管理指针:)在这种情况下,不需要任何带指针的数组!
使用虚拟内存的额外好处是它优化了内存页面的使用,所以如果你有这么大的数据对象,它就不会吞下10GB的ram。
顺便说一句:Windows支持直接内存页面与部分switch共享。在CPP中,您有such support。