ユーザーが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 ++インターフェイスの1つは、Elemental(https://github.com/poulson/Elemental/blob/master/src/core/imports/mpi.cpp)のインターフェイスです。アプローチ。特に、MpiMapは本質的な問題を解決すると思います。


これがそのような質問にふさわしい場所だとは思いません。
ジャックポールソン

その理由を教えてください。このサイトのMPI質問の多くは、ここの人々がこの質問に答える用意があることを示唆しています。また、1分間あたり0.2のアップ投票は、他の人があなたの評価に同意しないことを示唆しています。いずれにせよ、現在の会場が気に入らない場合は、これを投稿する別の場所を提案する方がより役立つでしょう。
ジェフ

質問は価値のあるものであり、もし範囲内であれば、より広範な計算科学のメーリングリストで貴重な回答を得ることができると思います。(おそらくNAダイジェスト、SIAM-CSE、またはG +の公開投稿でしょうか?)この質問は、主観的であるため、Stack Exchangeサイトには適していません(scicomp.stackexchange.com/help/dont-askを参照) 。回答が具体的で、特定のユースケースに焦点を合わせている限り(重要な繰り返しや重複なし)、オープンにしておく価値があると思います。
ジェフオックスベリー

@ジェフ:質問は私にとって世論調査によく似ています。私はそれが貴重であることに異議を唱えませんが、一つの受け入れられた答えがあるとは思いません。そのような質問は、MPIフォーラムにとっては普通のものではないでしょうか?
ジャックポールソン

@JackPoulson実装者が正しい答えだと思うものを知りたくありません。計算科学者に必要なものを知りたい。この点で、質問には客観的な答えがあります。正しい答えはありませんが、それが主観的な状況であることを意味するものではありません。
ジェフ

回答:


17

MPIの標準Cバインディングを使用するか、より高いレベルで何かを構築するかを決定しようとしたときに、長い間問題を考えてきたため、MPIへのC ++インターフェイスが一般的にあまり成功していないと思う理由をまず答えさせてください:

実際のMPIコード(たとえば、PETScまたは私の場合はdeal.II)を見ると、驚くべきことに、MPI呼び出しの数は実際にはそれほど多くないことがわかります。たとえば、500,000行のdeal.IIでは、最大100個のMPI呼び出ししかありません。この結果、MPI Cバインディングなどの低レベルインターフェイスの使用に伴う苦痛はそれほど大きくありません。逆に、より高いレベルのインターフェースを使用してもそれほど多くは得られません。

2番目の観察結果は、多くのシステムに複数のMPIライブラリがインストールされていることです(異なるMPI実装、または異なるバージョン)。たとえば、ヘッダーファイルだけで構成されていないboost :: mpiを使用する場合は、これが非常に困難になります。このパッケージも複数インストールする必要があるか、一部のパッケージとしてビルドする必要がありますboost :: mpiを使用するプロジェクト(ただし、boostが独自のビルドシステムを使用していることを考えると、これもまた問題です)。

したがって、これらはすべて、MPIへのC ++インターフェイスの現在の収穫に対して陰謀を企てていると思います。古いMPI C ++バインディングは利点を提供せず、外部パッケージは現実世界で困難を抱えていました。

これはすべて、ここに私が私が高レベルのインターフェースから持ちたいキラー機能になると思うものがあります:

  • これは一般的なものでなければなりません。変数のデータ型を指定することは、明らかにC ++のようなものではありません。もちろん、エラーにもつながります。ElementalのMpiMapクラスはすでに素晴らしい最初のステップになります(MpiMap::type変数を静的なconstにしない理由がわからないので、オブジェクトを作成せずにアクセスできます)。

  • 任意のデータ型をストリーミングする機能が必要です。

  • MPI_Op引数を必要とする操作(リダクションなど)は、C ++のstd::functionインターフェイスとうまく統合する必要があります。そのため、不器用に何かを登録するのではなく、関数ポインター(またはラムダ!)を渡すだけで簡単です。

boost :: mpiは実際にこれらすべてを満たします。ヘッダーのみのライブラリであれば、実際にはもっと人気があると思います。また、MPI 1.0以降の機能をサポートしていれば役立ちますが、正直に言ってください。これは、ほとんどの場合に必要なもののほとんどをカバーしています。


Boost :: MPIのシリアル化に関する問題の1つは、片側(別名RMA)では動作しないことです。ユーザーが興味を持っているC ++オブジェクトのMPIデータ型を作成できると思いますか?もちろん、理論的にはすべてがサポートされるべきですが、私はより実用的な目標から始めることを好みます。
ジェフ

シリアル化されたデータ型が片側通信で機能する可能性があると考えるのは間違いだと思います。これは、シリアル化にはデータを文字列にパックするだけで、反対側では再びアンパックするというビューを前提としています。ただし、シリアル化関数は、宛先ホストで何も実行できない場合に期待されるよりもはるかに多くのことができます(たとえば、他のオブジェクトへのポインターの追跡、シリアル化されたバイトのカウントなど)。私の見解では、C ++スタイルのシリアル化と片側通信は、単に非スターターです。誰もこれが機能することを期待してはならないと思うので、見逃されることはほとんどないでしょう。
ヴォルフガングバンガース

ウルフギャング、静的なconstメンバー変数を使用した場合、MpiMapがよりエレガントになることは間違いありません。:私は、実装を再編成しているgithub.com/poulson/Elemental/commit/...
ジャックPoulson

はい、はるかに良い:-)
ヴォルフガングバンガー

@WolfgangBangerthのmpiコールの数が少ないことについて+1。基本的に、mpiは計算を高速化することになっています。mpiの呼び出しは最小限に抑える必要があります。
チャールズ

6

ボールを転がすために、2つのニーズがあります。

  • インターフェイスは、MPI_IN_PLACEなどの冗長または不要な引数を排除できる必要があります。
  • このインターフェイスは、ElementalのMpiMapの組み込みデータ型を自動検出する必要があります。
  • 可能な場合はいつでも、ユーザー定義のデータ型をクラス用に構築する必要があります。

5

特定の優先順位のない私のリスト。インターフェイスは次のようにする必要があります。

  • ヘッダーのみで、依存関係<mpi.h>はありませんが、標準ライブラリ、
  • 汎用的で拡張可能であること、
  • 非ブロッキングのみである(ブロックする場合は、デフォルトではなく明示的にブロックする)
  • ノンブロッキングオペレーションの継続ベースのチェーンを許可します。
  • 拡張可能で効率的なシリアル化をサポート(Boost.Fusionなど、RMAで動作するように)、
  • 抽象化ペナルティがゼロである(つまり、少なくともCインターフェイスと同じ速度である)
  • 安全である(準備ができていない未来のデストラクタが呼び出されますか?-> std :: terminate!)、
  • DEBUG多数のアサーションを備えた強力なモードがあり、
  • 非常にタイプセーフです(すべてにints / void *はありません。タグをタイプにしたい!)、
  • ラムダで動作するはずです(たとえば、すべてが+ラムダを減らす)。
  • エラー報告およびエラー処理メカニズムとして例外を一貫して使用します(エラーコードはもうありません!関数の出力引数はありません!)、
  • 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ブロックせずにチェーン進めることができるかどうかを確認するには、まったく関係のないコード全体を複数の(またはすべての)中間ステップでテストする必要があります。


これは要件の厳しいリストです。それらのいくつかは、すべての実用的な目的のために不可能です(たとえば、ラムダを削減でサポートする)。ただし、全体としては、MPIコミュニティがサポートすることを目指しているもののタイプだと思います。
ジェフ

スレッドとランタイム環境に関しては、MPIはスレッドまたはOSスレッド(OSに応じてPOSIX、WindowsまたはSolaris)を内部的に使用します。ここで要件を理解しているかどうかはよくわかりません。
ジェフ

問題は、MPIがオペレーティングシステムから任意のスレッドを要求できることです。私のアプリケーションにはスレッドプールがあり、MPIがスレッドプールからそれらのスレッドを要求するようにします。現時点では、OpenMP、TBB、およびMPIを使用するアプリケーションがあり、それぞれ独自のスレッドプールがあり、それぞれに4倍のコアがある場合を除き、これは現在不可能です(通常は問題ではありません)。
gnzlbg 14

1
MPIは内部的にOSスレッドを使用できますが、通常は使用しません。私が精通しているすべてのケース(MPICH(2)、MVAPICH2、OpenMPI、CrayMPI)で、ユーザーが提供するランタイムオプションのみがこれを引き起こします。つまり、デフォルトではそうではありません。Blue Gene / Q MPIは例外ですが、この説明には関係ないような形式です。
ジェフ

@ジェフありがとう!単一のスレッドを使用しながら、MPIが複数の非ブロッキング呼び出しを処理する方法について詳しく説明していただけますか?コルーチン/グリーンスレッド/ファイバーを使用していますか?
gnzlbg 14

2

個人的には、Wolfgangが述べた正確な理由から、長い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)。ここで何を想像しますか?
ジェフ

@ジェフ私はthrust削減のためにそれをどのように行うのかという線に沿って何かを考えていました:docs.thrust.googlecode.com/hg/group__reductions.html
GradGuy

-1

githubプロジェクトeasyLambdaは、C ++ 14を使用したMPIへの高レベルインターフェイスを提供します。

このプロジェクトには同様の目標があり、現代のC ++を使用することで、この分野で実行できること、および実行されていることに関するアイデアが得られると思います。easyLambda自体と同様に他の努力を指導します。

パフォーマンスとコードの行に関する最初のベンチマークは、有望な結果を示しています。

ここに画像の説明を入力してください

以下は、提供する機能とインターフェイスの簡単な説明です。

インターフェイスは、固有の並列処理を提供するデータフロープログラミングと機能リスト操作に基づいています。並列処理は、タスクのプロパティとして表されます。.prll()プロパティを使用して、タスクのプロセス割り当てとデータ配布を要求できます。Webページコードリポジトリには、LAMMPS分子動力学後処理、熱方程式の明示的な有限差分ソリューション、ロジスティック回帰などを含む多数の例があります。例として、記事HPCで説明されている熱拡散問題は死にかけています...〜20行のコードで表現できます。

ここに詳細やサンプルコードを追加するのではなく、リンクを提供することで問題ないことを願っています。

Disclamer:私は図書館の著者です。私は、easyLambdaおよび同様の目標を追求する他のプロジェクトにとって有利なeasyLambdaの現在のインターフェースに関する建設的なフィードバックを得ることを望んで、何の害も与えないと信じています。


質問には、「説明とコンテキストを提供する長い回答を探しています。1行の回答だけでなく、回答が正しい理由を説明し、理想的には引用を使用してください。説明を含まない回答は削除できます。」。なぜあなたの答えはこの説明に合うほど完全だと思いますか?
ニコグアロ

私は、OPが求めているものと同様のインターフェースを提供するプロジェクトを指しています。私は答え自体にプロジェクトの動機と特徴の詳細を与え、OPや他の人に彼らがそれについてどう思うかを読んで提案させることができます。ただし、リンクのみを提供することにしました。私はあなたの主張を得る。回答への参照を含むテキストを追加しましょう。
Utkarsh Bhardwaj

@UtkarshBhardwaj:いくつかのコメント:(1)C ++とMPIをインターフェースするライブラリを書いてくれてありがとう。それは重要な仕事であり、あなたはそれに多くの仕事を入れたように見えます。(2)すぐにドキュメントを熟読します(再び、いい仕事です)、目立つのは、使用されるメソッドコマンドの長いチェーンです。(3)抽象化は機能的なパラダイムを想定しており、map-reduceのようなタスクに役立つように見えますが、MPIでプログラムを作成する人として、アルゴリズムを作り直して、私が知っているインターフェイスからあまり離れたくないです。
ジェフオックスベリー

(4)この例にはコミュニケーターがいないため、すべてにMPI_COMM_WORLDを使用している疑いがあり、ライブラリーの可能性が制限されています。(5)抽象化はMPI抽象化の上に構築されているようで、異なるバックエンドを持つことができます。(6)(3)-(5)に基づいて、このライブラリはMPIインターフェースではないと思います。その結果、このコメントはトピックから外れていると思います。
ジェフオックスベリー16年

@Geoffは貴重なフィードバックに感謝します。特定のポイントへの返信:2)チェーンは、ExpressionBuilderと呼ばれることもあります。機能的なスタイルで作曲を表現する一般的な方法です。ezlでこのスタイルで記述する必要はありません。最初に個々のユニットを記述してから構成し、[例](goo.gl/YzaL0k)を確認することができます。3)制御フローと命令型からデータフローと機能に移行することは難しいことを知っています。それぞれに長所と短所があります。ただし、後者については、真の有効性を知るためにさらに検討する必要があると思います。
Utkarsh Bhardwaj
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.