用户需要MPI C ++接口提供哪些功能?


28

MPI标准的3.0版本正式删除了C ++接口(先前已弃用)。尽管实现可能仍支持它,但MPI-3中的新功能没有MPI标准中定义的C ++接口。有关更多信息,请参阅http://blogs.cisco.com/performance/the-mpi-c-bindings-what-happened-and-why/

从MPI中删除C ++接口的动机是,与C接口相比,它没有任何重要价值。除“ s / _ / :: / g”外,几乎没有区别,并且未使用C ++用户习惯的许多功能(例如,通过模板自动确定类型)。

作为参加MPI论坛并与许多实现了自己的MPI C函数C ++接口的C ++项目一起工作的人,我想知道MPI C ++接口的理想功能是什么。尽管我什么也不做,但我希望看到一个满足许多用户需求的独立MPI C ++接口的实现。

是的,我熟悉Boost :: MPI(http://www.boost.org/doc/libs/1_54_0/doc/html/mpi.html),但它仅支持MPI-1功能,并且序列化模型应为支持RMA极其困难。

我喜欢的一个MPI的C ++接口是Elemental(https://github.com/poulson/Elemental/blob/master/src/core/imports/mpi.cpp),所以也许人们可以提供一些专业知识方法。特别是,我认为MpiMap解决了一个基本问题。


我认为这不是解决此类问题的合适地点。
Jack Poulson

你能给出一些原因吗?该站点上的许多MPI问题都向我暗示,这里的人们准备回答这个问题。此外,每分钟0.2次投票表明其他人不同意您的评估。无论如何,如果您不喜欢当前的地点,建议推荐一个替代位置来张贴此内容会更有帮助。
杰夫

这个问题是一个有价值的问题,我认为它可以在更广泛的计算科学邮件列表上得到一些有价值的答复,只要它在范围之内。(也许是NA-digest,SIAM-CSE甚至是G +上的公开帖子?)此问题可能不适用于Stack Exchange网站,因为它是主观的(请参阅scicomp.stackexchange.com/help/dont-ask) 。只要答案是具体的并且专注于特定用例(没有明显的重复或重叠),我认为值得保持开放。
Geoff Oxberry

@Jeff:这个问题对我来说就像一次民意测验。我并不认为这很有价值,但是我看不出有一个公认的答案。对于MPI论坛来说,这样的问题会不寻常吗?
Jack Poulson

@JackPoulson我不想知道实施者认为正确的答案是什么;我想知道计算科学家需要什么。在这方面,这个问题有客观的答案。没有一个正确的答案,但这并不意味着这是一个主观的情况。
杰夫

Answers:


17

让我首先回答一下,为什么我认为C ++与MPI的接口通常并不太成功,在试图决定是否只使用MPI的标准C绑定还是在更高级别上构建时,已经考虑了很长时间:

当您查看现实世界中的MPI代码(例如,PETSc或我的案例交易II)时,可能会发现令人惊讶的是,MPI调用的数量实际上并不是很大。例如,在500k交易行II中,只有约100个MPI调用。其结果是,使用低级接口(例如MPI C绑定)所涉及的痛苦不会太大。相反,通过使用更高级别的接口并不会获得太多收益。

我的第二个观察结果是,许多系统都安装了多个MPI库(不同的MPI实现或不同的版本)。如果您想使用不仅仅由头文件组成的boost :: mpi,这会带来很大的困难:或者还需要多次安装此软件包,或者需要将其构建为其中的一部分。使用boost :: mpi的项目(但这又是一个问题,因为boost使用自己的构建系统,这与其他任何东西都不一样)。

因此,我认为所有这些都与当前MPI的C ++接口的阴谋密不可分:旧的MPI C ++绑定没有提供任何优势,外部程序包在现实世界中遇到了困难。

总而言之,这就是我想从更高级别的界面获得的杀手级功能:

  • 它应该是通用的。必须指定变量的数据类型绝对不是C ++。当然,这也会导致错误。Elemental的MpiMap类已经是不错的第一步(尽管我无法弄清楚为什么该MpiMap::type变量不是静态const,因此无需创建对象即可对其进行访问)。

  • 它应该具有用于​​流传输任意数据类型的功能。

  • 需要自MPI_Op变量的操作(例如,归约)应与C ++的std::function界面很好地集成在一起,因此只需传递函数指针(或lambda!)即可,而不必笨拙地注册某些东西。

boost :: mpi实际上满足了所有这些要求。我认为,如果这是仅标头的库,那么在实践中它将流行得多。如果它支持MPI 1.0之后的功能,也将有所帮助,但是老实说:这涵盖了我们大部分时间的大部分需求。


Boost :: MPI中的序列化问题之一是它不适用于单面(又名RMA)。您是否认为可以为用户感兴趣的C ++对象创建MPI数据类型?当然,从理论上讲,所有方面都应得到支持,但我更愿意以更务实的目标开始。
杰夫

我认为认为序列化数据类型可以用于单面通信是错误的。这是假定序列化仅涉及将数据打包到字符串中,而另一方面又将其拆包。但是,如果您无法在目标主机上执行任何操作,则序列化功能所能起到的作用(例如,跟踪指向其他对象的指针,对已序列化的字节进行计数等)比人们期望的更多。我的观点是,C ++风格的序列化和单面通信完全是入门。我认为没有人应该期望它能奏效,所以不会错过任何机会。
Wolfgang Bangerth

沃尔夫冈,您好,如果使用静态const成员变量,则MpiMap会更优雅,这是正确的。我重新组织实施:github.com/poulson/Elemental/commit/...
杰克Poulson的

是的,更好:-)
Wolfgang Bangerth

+1不多的mpi调用@WolfgangBangerth。从根本上讲,MPI应该使计算速度更快,因此您希望最小化MPI调用,因为它们会花费您!
查尔斯

6

为了使事情顺利进行,这是我的两个需求:

  • 该接口应能够消除冗余或不必要的参数,例如MPI_IN_PLACE。
  • 该界面应自动检测ala Elemental的MpiMap内置数据类型。
  • 如果可能,应为类构造用户定义的数据类型。

5

我的列表没有特别的优先顺序。该界面应:

  • 仅是标头,除了<mpi.h>和标准库之外,没有任何依赖关系,
  • 具有通用性和可扩展性
  • 无阻塞(如果你想阻止,则阻止明确,而不是由默认值),
  • 允许对非阻塞操作进行基于连续的链接,
  • 支持可扩展且有效的序列化(类似于Boost.Fusion,可与RMA配合使用),
  • 具有零抽象损失(即至少与C接口一样快),
  • 是安全的(未就绪的未来的析构函数称为?-> std :: terminate!),
  • 具有DEBUG大量断言的强大模式,
  • 非常安全的类型(没有更多的int / void *用于所有内容,我想让标签成为类型!),
  • 它应该与lambda一起工作(例如,所有reduce + lambda),
  • 一致地使用异常作为错误报告和错误处理机制(不再有错误代码!不再有函数输出参数!),
  • MPI-IO应该以Boost.AFIO的样式提供无阻塞的I / O接口,
  • 并遵循良好的现代C ++接口设计规范(定义常规类型,非成员非朋友功能,在移动语义上发挥出色,支持范围操作...)

附加功能:

  • 请允许我选择MPI环境的执行程序,即它使用哪个线程池。现在,您可以同时具有混合了OpenMP,MPI,CUDA和TBB的应用程序...,每个运行时都认为它拥有环境,因此每次感觉到操作系统时都向操作系统请求线程它。认真吗

  • 使用STL(和Boost)命名约定。为什么?每个C ++程序员都知道这一点。

我想写这样的代码:

auto buffer = some_t{no_ranks};
auto future = gather(comm, root(comm), my_offsets, buffer)
              .then([&](){
                /* when the gather is finished, this lambda will 
                   execute at the root node, and perform an expensive operation
                   there asynchronously (compute data required for load 
                   redistribution) whose result is broadcasted to the rest 
                   of the communicator */
                return broadcast(comm, root(comm), buffer);
              }).then([&]() {
                /* when broadcast is finished, this lambda executes 
                   on all processes in the communicator, performing an expensive
                   operation asynchronously (redistribute the load, 
                   maybe using non-blocking point-to-point communication) */
                 return do_something_with(buffer);
              }).then([&](auto result) {
                 /* finally perform a reduction on the result to check
                    everything went fine */
                 return all_reduce(comm, root(comm), result, 
                                  [](auto acc, auto v) { return acc && v; }); 
              }).then([&](auto result) {
                  /* check the result at every process */
                  if (result) { return; /* we are done */ }
                  else {
                    root_only([](){ write_some_error_log(); });
                    throw some_exception;
                  }
              });

/* Here nothing has happened yet! */

/* ... lots and lots of unrelated code that can execute concurrently 
   and overlaps with communication ... */

/* When we now call future.get() we will block 
   on the whole chain (which might have finished by then!).
*/

future.get();

想一想如何使用MPI_C链接所有这些操作request。您将必须通过大量不相关的代码在多个(或每个)中间步骤中进行测试,以查看是否可以不阻塞地推进链。


这是要求的清单。其中的一些对于所有实际目的都是不可能的(例如,支持减少的lambda)。但是,总的来说,我认为这是MPI社区应该支持的事情。
杰夫

至于线程和运行时环境,MPI在内部不使用任何线程或OS线程(POSIX,Windows或Solaris,具体取决于OS)。我不太确定我了解这里的要求。
杰夫

问题是MPI可以从操作系统中任意请求线程。我的应用程序有一个线程池,我希望MPI从我的线程池中请求那些线程。除非您有一个使用OpenMP,TBB和MPI的应用程序,并且每个应用程序都有自己的线程池,每个线程池的内核数是4倍,否则这目前是不可能的(通常不是问题)。
gnzlbg 2014年

1
MPI可以但通常不在内部使用OS线程。在我所熟悉的每种情况下(MPICH(2),MVAPICH2,OpenMPI,CrayMPI),只有用户提供的运行时选项才会导致这种情况发生,即默认情况下不会。Blue Gene / Q MPI是一个例外,但形式与本讨论无关。
杰夫

谢谢@杰夫!您能否详细说明MPI在使用单个线程时如何处理多个非阻塞调用?它使用协程/绿色线程/纤维吗?
gnzlbg 2014年

2

就我个人而言,由于沃尔夫冈提到的确切原因,我真的不介意调用长C样式的函数。实际上,您几乎不需要调用它们的地方,即使那样,它们几乎总是被一些高级代码所包裹。

使用C风格的MPI真正困扰我的唯一事情是自定义数据类型,以及程度较小的自定义操作(因为我使用它们的频率降低了)。至于自定义数据类型,我想说一个好的C ++接口应该能够支持通用且有效的处理方式,最有可能是通过序列化的方式。当然,这是boost.mpi采取的路线,如果您小心一点,可以节省大量时间。

至于boost.mpi具有额外的依赖关系(尤其boost.serialization是本身不是仅标头的),我最近遇到了一个称为谷物的仅标头的C ++序列化库,这似乎很有希望。授予它需要一个符合C ++ 11的编译器。可能值得研究并将其用作类似于的基础boost.mpi


请注意,我并不一定要在MPI标准中添加任何内容。我完全同意MPI应该几乎总是“被一些高级代码包裹”,所以我想知道的是,该高级代码是什么样的?Elemental有一个不错的方法,但是对于所有情况都是最好的吗?如果有人希望有一个MPI的C ++接口,试图使很多人感到高兴,那会是什么样?
杰夫

@杰夫 对我来说:1.我希望能够轻松发送自定义数据类型。2.我希望能够通过自定义操作轻松执行归约。我也认为1比2更为重要/有用
GradGuy

我没有看到C ++如何做任何神奇的wrt(2)。您在这里想像什么?
杰夫(Jeff)

@Jeff我正在思考如何thrust减少排放的方法:docs.thrust.googlecode.com/hg/group__reductions.html
GradGuy 2013年

-1

github项目easyLambda提供了C ++ 14与MPI的高级接口。

我认为该项目具有类似的目标,并且将通过使用现代C ++对该领域中可以做和正在做的事情给出一些想法。指导其他工作以及easyLambda本身。

最初的性能和代码行基准已经显示出令人鼓舞的结果。

在此处输入图片说明

以下是它提供的功能和界面的简短说明。

该接口基于提供固有并行性的数据流编程和功能列表操作。并行性表示为任务的属性。可以使用.prll()属性请求任务的进程分配和数据分配。网页代码库中有很多示例,包括LAMMPS分子动力学后处理,热方程的显式有限差分解决方案,逻辑回归等。作为示例,HPC文章中讨论的热扩散问题正在逐渐消失...可以用约20行代码表示。

我希望可以提供链接,而不是在此处添加更多详细信息和示例代码。

Disclamer:我是图书馆的作者。我相信希望获得对easyLambda当前界面的建设性反馈不会有任何危害,这可能对easyLambda和追求类似目标的任何其他项目都有利。


问题说:“ 我们正在寻找能提供一些解释和上下文的长答案。不要仅仅给出单行答案;而是要解释为什么您的答案正确,最好是带有引文。不包括解释的答案可能会被删除。 。 ”。您为什么认为您的答案足够完整以适合此描述?
nicoguaro

我指的是一个提供与OP要求类似的界面的项目。我可以在答案本身中提供项目动机和功能的详细信息,并让OP和其他人阅读并提出他们对此的想法。但是,我选择仅提供链接。我明白你的意思。让我添加一些参考答案的文本。
Utkarsh Bhardwaj

@UtkarshBhardwaj:一些评论:(1)感谢您编写了将C ++与MPI接口的库。这是一项重要的工作,看起来您已经付出了很多工作。(2)快速阅读文档(再次,很好的工作),突出的是所使用的方法命令的长链,从样式上看...调试起来很痛苦,即使您对它们进行了很好的格式化。(3)抽象假定一个功能性范例,该范例对于类似于map-reduce的任务很有用,但是作为在MPI中进行编程的人,我不想重做算法,也不想离开我所知道的接口太多。
Geoff Oxberry's

(4)在示例中,我看不到任何传播者,这使我怀疑您在使用MPI_COMM_WORLD进行所有操作,并限制了库的潜力。(5)抽象似乎建立在MPI抽象的基础上,并且可能具有不同的后端。(6)基于(3)-(5),我认为该库不是MPI接口,因此我认为此注释不合时宜。
Geoff Oxberry's

@Geoff感谢您的宝贵反馈,非常感谢。对特定观点的答复:2)链接有时称为ExpressionBuilder。这是一种以功能风格表达构图的常见方式。不必在ezl中以这种样式编写。可以先编写单个单元,然后编写它们,然后检查[示例](goo.gl/YzaL0k)。3)我知道很难从控制流和命令性转到数据流和功能。每个都有优点和缺点。但是,我认为需要进一步研究后者以了解其真正的功效。
Utkarsh Bhardwaj
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.