gpt4 book ai didi

c++ - 复杂对象的 MPI 共享内存

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:13:05 25 4
gpt4 key购买 nike

我有一个在许多 CPU 内核上运行的大规模代码,可能跨越多个计算节点。代码使用 C++ 并与 OpenMPI 并行化。

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

到目前为止,我一直在为每个 MPI 进程提供该对象的一个​​拷贝;但这意味着我的 RAM 严重受限,无法使用节点的全部 CPU 能力。所以,我一直在阅读 MPI 3 规范中关于共享内存的内容。

我的问题是:跨 MPI 进程共享复杂对象的最佳方式是什么?在我找到的所有示例中,都会创建 MPI 共享内存窗口并用于交换简单的数据结构( float 、整数数组等)。我的全局对象是一个自定义的类类型,它包含了一些成员变量,其中一些是指针,还有很多是其他复杂的类类型。因此,我觉得我不能只调用 MPI_Win_allocate_shared 并传入我的复杂对象的地址,特别是因为我想共享有关成员变量的所有信息(特别是,我希望共享指针类型成员变量的基础值 - 即跨 MPI 进程共享“深层拷贝”,每个进程中的所有虚拟内存地址都是正确的)。

是否有可能通过 MPI 共享内存实现这种“深度共享”,如果可以,是否有这样做的“最佳实践”?还是另一个库(例如 boost interprocess)会让这对我来说更可行/更直接?

附言如果我找不到好的解决方案,我将求助于混合 MPI+pthreads 方法,我知道我可以在每个节点上使用 pthreads 轻松地拥有这个全局对象。但我真的希望找到一个优雅的纯 MPI 解决方案。

最佳答案

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

补充回答1:

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

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

使用虚拟内存的额外好处是它优化了内存页面的使用,因此如果您有如此大的数据对象,它不会占用 10GB 的内存。

顺便说一句:Windows 支持直接内存页面与一些共享 switch在部分。在 CPP 中你有 such support

关于c++ - 复杂对象的 MPI 共享内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37719164/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com