共享内存,MPI和排队系统

Blk*_*ght 20 c++ mpi shared-memory pbs boost-interprocess

我的unix/windows C++应用程序已经使用MPI进行了并行化:作业被分割为N cpus,并且每个块都是并行执行,非常高效,非常好的速度缩放,工作正确完成.

但是在每个过程中都会重复一些数据,并且由于技术原因,这些数据不能轻易地通过MPI(...)进行分割.例如:

  • 5 Gb的静态数据,为每个进程加载完全相同的东西
  • 可以在MPI中分发的4 Gb数据,使用的CPU越多,每个CPU的RAM越小.

在4 CPU工作中,这意味着至少有20Gb的RAM负载,大部分内存"浪费",这很糟糕.

我正在考虑使用共享内存来减少总体负载,每台计算机只会加载一次"静态"块.

所以,主要问题是:

  • 是否有任何标准的MPI方式在节点上共享内存? 某种现成的+免费图书馆?

    • 如果没有,我将使用boost.interprocess和使用MPI调用来分发本地共享内存标识符.
    • 共享内存将由每个节点上的"本地主机"读取,并以只读方式共享.不需要任何类型的信号量/同步,因为它不会改变.
  • 任何性能损失或特别问题要警惕?

    • (不会有任何"字符串"或过于奇怪的数据结构,一切都可以归结为数组和结构指针)
  • 该作业将在PBS(或SGE)排队系统中执行,如果进程不干净退出,我想知道这些是否会清理特定于节点的共享内存.

jan*_*neb 8

高性能计算(HPC)中一种日益普遍的方法是混合MPI/OpenMP程序.即你有N个MPI进程,每个MPI进程有M个线程.此方法很好地映射到由共享内存多处理器节点组成的集群.

更改为这种分层并行化方案显然需要一些或多或少的侵入性更改,OTOH如果正确完成,除了减少复制数据的内存消耗外,还可以提高代码的性能和可伸缩性.

根据MPI实现,您可能会也可能无法从所有线程进行MPI调用.这是由MPI_Init_Thread()函数的requiredprovided参数指定的,您必须调用它而不是MPI_Init().可能的值是

{ MPI_THREAD_SINGLE}
    Only one thread will execute. 
{ MPI_THREAD_FUNNELED}
    The process may be multi-threaded, but only the main thread will make MPI calls (all MPI calls are ``funneled'' to the main thread). 
{ MPI_THREAD_SERIALIZED}
    The process may be multi-threaded, and multiple threads may make MPI calls, but only one at a time: MPI calls are not made concurrently from two distinct threads (all MPI calls are ``serialized''). 
{ MPI_THREAD_MULTIPLE}
    Multiple threads may call MPI, with no restrictions. 

根据我的经验,像Open MPI这样的现代MPI实现支持最​​灵活的MPI_THREAD_MULTIPLE.如果您使用较旧的MPI库或某些专用架构,则可能会更糟糕.

当然,您不需要使用OpenMP进行线程化,这只是HPC中最受欢迎的选项.您可以使用例如Boost线程库,Intel TBB库或直接pthread或Windows线程.

  • 我不确定混合方法是否越来越普遍.以下是证据表明它可能不值得采取的一个例子 - http://www.pdc.kth.se/education/historical/2008/PRACE-P2S2/coursework/handouts.html#hybrid是的,它是一个很好的概念,但与修改您的应用程序所需的努力相比,在实践中具有可疑的价值. (2认同)

Mik*_* D. 7

我没有使用MPI,但如果它像其他IPC库一样,我已经看到隐藏其他线程/进程/无论是在相同或不同的机器上,那么它将无法保证共享内存.是的,如果该机器本身提供共享内存,它可以处理同一台机器上两个节点之间的共享内存.但是,由于提出了复杂的一致性问题,尝试在不同机器上的节点之间共享内存将是非常困难的.我希望它只是没有实现.

实际上,如果您需要在节点之间共享内存,最好的办法是在MPI之外执行此操作.我认为您不需要使用boost.interprocess-style共享内存,因为您没有描述不同节点对共享内存进行细粒度更改的情况; 它是只读的或分区的.

John和deus的答案涵盖了如何在文件中映射,这绝对是你想要为5 Gb(千兆?)静态数据做的.每个CPU的数据听起来都是一样的,你只需要向每个节点发送一条消息,告诉它应该抓取哪个文件部分.操作系统应该将虚拟内存映射到物理内存到文件.

至于清理......我认为它不会对共享内存进行任何清理,但是mmap当清理进程时,应该清理ed文件,因为文件已关闭(应该释放它们的内存映射).我不知道有什么警告CreateFileMapping.

boost.interprocess当进程终止时,不会清除实际的"共享内存"(即).如果可能的话,我建议尝试杀死进程并查看遗留的内容.