我希望在Beowulf集群中并行化一些代码,这样所涉及的CPU就不会共享地址空间。我想在外部循环中并行化函数调用。函数调用没有任何“重要”副作用(尽管它们使用随机数生成器,分配内存等)。
我看过像MPI这样的库,我看到的问题是它们似乎使得在节点之间传递复杂的对象图非常重要。我的函数的输入是一个指向非常复杂的对象图的this指针。我的函数的返回类型是另一个复杂的对象图。
在语言无关的级别(我正在使用D编程语言,我几乎可以肯定这里没有固定解决方案,但我愿意创建一个),是否有“典型”方式处理跨节点传递复杂状态的问题?理想情况下,我希望将状态复制的详细信息完全抽象出去,并使调用看起来几乎像普通函数调用一样。我并不关心在网络上复制这么多状态并不是特别有效,因为所讨论的并行程度非常粗糙,可能无关紧要。
编辑:如果没有简单的方法来传递复杂状态,那么通常如何使用消息传递?在我看来,任何涉及通过网络复制数据的内容都需要粗粒度并行,但粗粒度并行性通常需要通过复杂状态,以便在一个工作单元中完成大量工作。
答案 0 :(得分:3)
我做了一些MPI编程,但我不知道在进程之间传递复杂状态(如你所描述的)的任何典型的方式。以下是我一直在思考你的问题,它可能与你自己的想法相符......
我猜测你的复杂对象图在内存中由数据块和指向其他数据块的指针表示 - 这是图的常见实现。如何最好地将这些COG之一(缩写)从一个进程的地址空间移动到另一个进程的地址空间?如果指针是一个内存地址,一个地址空间中的指针在另一个地址空间中没有用,所以你必须将它转换成某种中性形式进行传输(我认为?)。
因此,要发送COG,必须将其置于某种形式,接收进程可以在其自己的地址空间中构建一个本地版本的图形,其指针指向本地存储器地址。你有没有把这些COG写成文件?如果是这样,您已经有一个可以运输的表格。我讨厌建议它,但你甚至可以使用文件在进程之间进行通信 - 这可能比D和MPI的组合更容易处理。你的选择!
如果您没有COG的文件表格,您可以轻松地将它们表示为邻接矩阵或列表吗?换句话说,计算出你自己的交通代表?
如果您可以在进程之间传递COG而不将其从基于指针的转换为某些更静态的结构(如数组或记录),我会非常惊讶(但很高兴学习)。
编辑,以响应OP的编辑。如果复杂状态表示为值而不是指针,MPI确实提供了简单的方法来传递复杂状态。您可以在内部或自定义MPI数据类型中传递复杂状态;正如其他答案之一所示,这些都是灵活和有能力的。如果我们的程序没有以MPI自定义数据类型可以处理的形式保存复杂状态,则必须编写函数来打包/解包到消息友好表示。如果你能做到这一点,那么你的消息调用将看起来(对于大多数用途),如函数调用。
关于复杂状态和并行性的颗粒性问题,我不确定我是否非常关注你。我们(如果你想或不想把你自己包含在这种全面的概括中)通常采用MPI编程,因为我们无法从单个处理器中获得足够的性能,我们知道我们将通过等待延迟计算的代价为了沟通,我们努力减少这种惩罚,但最终我们接受惩罚作为并行化的成本。当然,有些工作太小或太短都无法从并行化中受益,但我们(并行计算人员)所做的很多工作太大而且运行时间太长而无法实现并行化
答案 1 :(得分:2)
您可以使用自定义MPI数据类型执行奇妙的操作。我目前正在开发一个项目,其中有几个MPI进程跟踪虚拟空间中的粒子,当粒子从一个进程的区域跨越到另一个进程时,它们的数据(位置/速度/大小/等)必须是通过网络发送。
我实现这一目标的方法如下:
1)所有进程共享一个粒子的MPI Struct数据类型,该粒子包含其所有相关属性,以及它们在内存中的位移与粒子对象的基址相比。
2)在发送时,进程迭代它存储粒子的任何数据结构,记下每个需要发送的内存地址,然后构建一个Hindexed数据类型,其中每个块为1 long(上面提到的粒子数据类型)并从先前记下的内存地址开始。发送结果类型的1个对象将以类型安全的方式通过网络发送所有必要的数据。
3)在接收端,事情有点棘手。接收过程首先将“空白”粒子插入其自己的数据结构中:“空白”表示将从另一个进程接收的所有属性初始化为某个默认值。记下新插入的粒子的存储器地址,并从这些地址创建类似于发送器的数据类型。将发件人的邮件作为此类型的单个对象接收,将以类型安全的方式自动将所有数据解压缩到所有正确的位置。
这个例子更简单,因为粒子之间没有关系(就像图形的节点之间一样),但你可以用类似的方式传输这些数据。
如果上面的描述不清楚,我可以发布实现它的C ++代码。
答案 2 :(得分:2)
我不确定我是否正确理解了这个问题所以请原谅我,如果我的回答是关闭的话。根据我的理解,您希望使用MPI发送非POD数据类型。
可以执行此操作的库是Boost.MPI。它使用序列化库来发送甚至非常复杂的数据结构。但是有一个问题:如果你使用Boost.Serialize不知道的复杂结构,你必须自己提供代码来序列化数据。
我认为消息传递通常用于传输POD数据类型。
我不允许发布更多链接,所以这里是我想要包含的内容:
POD说明:www.fnal.gov/docs/working-groups/fpcltf/Pkg/ISOcxx/doc/POD.html
序列化库:www.boost.org/libs/serialization/doc
答案 3 :(得分:0)
这取决于您的数据的组织。如果在对象中使用指针或自动内存,则很难。如果您可以将对象组织为在内存中连续,则有两种选择:将内存作为字节发送,将其强制转换为接收器上的对象类型,或者为对象定义mpi派生类型。但是,如果使用继承,由于对象在内存中的布局方式,事情会变得复杂。
我不知道你的问题,但如果你手动管理内存,也许可以看看ARMCI。