並列科学計算ソフトウェア開発言語?


18

ゼロから並列科学計算ソフトウェアを開発したいです。どの言語から始めるべきかを考えてみたい。このプログラムは、txtファイルへのデータの読み取り/書き込みと、多くのLU分解およびスパース線形ソルバーの使用を伴う大量の計算を並行して実行します。私が考えていたソリューションの候補は、OpenMPまたはco-arrayを備えたFortran 2003/2008、openmp cilk +またはTBB、pythonを備えたC ++です。その他の文書化された提案は大歓迎です!私はC、Fortran、Javaを(この順序で)よく知っています。私はPythonでいくつかのスクリプトを作成しましたが、基本的なものです。

fortranは非常に高速ですが、保守や並列化が難しいことは知っています。私が好きなPythonなどの外部ライブラリを使用しない限り、C ++は遅いと言われていますが、フルスケールの産業レベルのソフトウェアを書くことは現実的ですか?

ソフトウェアは、大量のデータを処理でき、科学計算で効果的である必要があります。パフォーマンスが重要です。

背景については、Fortranで書かれた動作するソフトウェアが既にあります。多くの人々が長年にわたって開発に関わっており、コードは本当に汚れています。コードの維持と並列化は悪夢であることが証明されており、代替案を考えています。

ペトロス


5
C ++としては、Fortranを保守するのは難しいとは思いません。保守性は、言語の選択ではなく、大部分のグッドプラクティスに関連しています。C ++の遅さは売り過ぎです。また、データサイズと所要時間の要件を説明するために、この投稿を充実させることをお勧めします。「大きな」ものは、​​話し相手に応じて9桁または10桁異なることがあります。
ビル・バルト

@BillBarth既存のFortranコードの問題は、3人が異なるプラクティスを使用して関与していたことです。私はCのバックグラウンド、F77のバックグラウンドからの一人、Matlabからの一人です。データは割り当て可能ではなく、最大サイズのシステムに合わせてサイズ設定されています(最近関与しました)。このコードは、350秒(経過時間)で240秒の時間範囲で72000の微分方程式と74000の代数方程式を使用してシステムをシミュレートできました。OpenMPを使用して並列化することで、それを170秒に減らしました。ここで、いくつかのケースを並行して実行する必要があります(セキュリティチェックのためにスイープするため)。
電気

4
@BillBarthはC ++のスキルを売るにはあまりにも控えめですが、「C ++の遅さは売られすぎている」という声明で寛大すぎます。scicomp.stackexchange.comには多くのC ++対Fortranスレッドがあり、この非常に疑問を議論しており、一般的な結論は、ほとんどすべての場合でC ++がFortranよりも遅いというだけでは事実ではないというものでした。個人的には、今日では都市の神話と考えることができると思います。何非常に真にすると、コードのアカウントの保守性を考慮する場合、Fortranは、今日は非常にうまくやっていないということです。
ウォルフガングバンガース

2
@BillBarthなど、Fortran、C ++、およびその他の言語の一般的なメリットについて引き続き議論したい場合は、scicompチャットルームに行ってください。
アロンアフマディア

1
@AronAhmadia:ああ、さあ、Jedに言いたいことがたくさんあります;
Wolfgangバンガース

回答:


19

要件を分析してみましょう。

  • 保守性
  • テキストデータの読み取り/書き込み
  • LU分解のための強力なインターフェース/機能
  • スパース線形ソルバー
  • 大規模データに対するパフォーマンスとスケーラビリティ

このリストから、次の言語を検討します。

C、C ++、Fortran、Python、MATLAB、Java

ジュリアは有望な新しい言語ですが、コミュニティはまだその周辺で形成されており、主要な新しいコードでは展開されていません。

テキストデータの読み取り/書き込み

これは、どのプログラミング言語でも簡単に正しく実行できます。I / Oアクセスを適切にバッファリングおよび合体していることを確認してください。そうすれば、考慮すべき言語のいずれかから優れたパフォーマンスが得られます。C ++でストリームオブジェクトを使用する方法を知らない限り、ストリームオブジェクトは避けてください。

LU分解のための強力なインターフェース/機能

密なLU分解を実行している場合、並列機能にはLAPACKまたはScaLAPACK / Elementalを使用する必要があります。LAPACKとScaLAPACKはFortranで書かれており、ElementalはC ++で書かれています。3つのライブラリはすべて高性能であり、十分にサポートされ、文書化されています。検討する必要のある任意の言語からそれらに接続できます。

スパース線形ソルバー

最高の無料で利用可能なスパース線形ソルバーは、ほとんどすべてが文書化されサポートされているCで記述されたPETScを介して利用できます。考慮すべき言語のいずれかからPETScに接続できます。

大規模データに対するパフォーマンスとスケーラビリティ

あなたが言及する唯一の並列プログラミングのパラダイムは、共有メモリベースです。つまり、MPIベース(メッセージパッシング)の分散メモリコンピューティングアプローチを検討していません。私の経験では、分散メモリソリューションを使用すると、12を超えるコアをはるかに超えるコードを書く方がはるかに簡単です。ほとんどすべての大学の「クラスター」は最近MPIベースであり、大規模な共有メモリマシンは高価であり、それに応じてまれです。アプローチにはMPIを考慮する必要がありますが、選択するプログラミングパラダイムに関係なく、私のアドバイスが適用されます。

オンノードのパフォーマンスに関して、数値ルーチンを自分で作成する場合、Fortranで優れたシリアルパフォーマンスを得るのが最も簡単です。C、C ++、またはPythonの経験が少しあれば、非常に匹敵するパフォーマンスを得ることができます(Fortranでは、CとC ++は完全に同等です)MATLABは、JITコンパイラーと非常に優れた線形代数表現性によりこれを行います。Pythonから要求されたパフォーマンスを得るには、おそらくCython、numpy、numexprを使用するか、数値カーネルを埋め込む必要があります。Javaのパフォーマンスについてコメントすることはできません。言語をよく知らないからです。しかし、専門家によって書かれたものであれば、Pythonからそれほど遠くないのではないかと思います。

インターフェースに関する注意

あなたがあなたが考えているプログラミング言語のいずれかであなたが望むすべてをすることができるだろうと確信していることを願っています。Javaを使用している場合、Cインターフェイスは少し難しくなります。Pythonには、ctypes、Cython、およびf2pyを介した優れたCおよびFortranインターフェースのサポートがあります。LAPACKはすでにラップされており、scipyから入手できます。MATLABは、ネイティブライブラリに必要なすべての機能を備えていますが、スケーラブルではないか、クラスター上で実行するのが特に簡単ではありません。Javaは、JNIを使用してCおよびFortranインターフェースをサポートできますが、クラスターや科学計算用の並列ソフトウェアでは一般的に見られません。

保守性

これの多くは個人的な趣味になりますが、保守性に関する一般的なコンセンサスは、ソフトウェアのコードの行数を最小限に抑え、明確に定義されたインターフェースでモジュラーコードを記述し、計算ソフトウェアに提供することです実装の正確さと機能を検証するテスト。

勧告

私は個人的にPythonで運が良かったので、多くの計算プロジェクトにPythonをお勧めします。私はあなたのプロジェクトのためにそれを強く検討すべきだと思います。PythonとMATLABは、おそらく科学計算に利用できる言語の中で最も表現力のあるものです。Pythonを他のプログラミング言語に簡単に接続できます。f2pyを使用して、現在のFortran実装をラップし、機能を維持していることを確認しながら、Pythonで必要な部分を個別に書き換えることができます。現時点では、Python 2.7の公式実装scipyの組み合わせをお勧めします。自由に利用可能なEnthought Python Distributionからこのスタックを簡単に開始できます

これのほとんどは、C、C ++、またはFortranでも実行できます。CとC ++は、多くの経験を持つプロの開発者にとって非常に魅力的な言語ですが、頻繁に新しい開発者を旅行し、この意味で、よりアカデミックなコードにはおそらく素晴らしいアイデアではありません。FortranとMATLABは学術的な計算で人気がありますが、Pythonが提供する高度なデータ構造と表現力には弱いです(たとえば、Python dictオブジェクトを考えてください)。

関連する質問:


1
非常によく文書化された、包括的な答え。Fortranでは、多くのLapackを使用しています。Pythonを見て、Fortranコードをラップして、最初はゆっくりとPythonに移行しようとします。私を怖がらせる唯一のことは、私が持っているかもしれない25%の時間オーバーヘッドです。しかし、より表現力豊かなコードとより優れた並列コンピューティング処理の利点があれば、私はそれを選びます。共有メモリについて言及したのは、WindowsおよびLinux環境のUniの研究者の2,4,8,24,48コアの共有メモリコンピュータで、ソフトウェアが現在インタラクティブに実行されている(データを変更して再実行する)ためです。
電気

3
Pythonで記述された数値カーネルの25%のオーバーヘッドをどのように主張できるかわかりません。純粋なPythonの数値カーネルは、Cの100倍の速度であることがよくあります。Numpyとnumexprは特定の式で適切な仕事をすることができますが、Pythonで新しい数値カーネルを書くことはほとんどありません。Cythonは高速化できますが、通常はCの25%以内ではありません。Pythonは素晴らしい「接着」言語ですが、Aronはパフォーマンスに敏感なタスクの汎用ソリューションとしてそれを売り過ぎていると思います。
ジェドブラウン

FortranはI / Oで多くの構造を必要とするため、I / OはFortranの弱点です。Cythonと仕事をしている私の研究室の同僚と話すことから得た私の経験は、JedがCythonについて語ったことと一致しています。そのうちの少なくとも1人は、パフォーマンス重視のタスクのためにCythonを置き換えるために手動で調整されたCを記述します。そして、結果のCコードを呼び出すPythonのパフォーマンスはAronの主張に近いと思います。また、PETScとPythonに言及する場合は、petsc4pyに言及することもできます。私が最後に見た(これは数年前)が、Java用の優れたMPIインターフェイスはありませんでした。それは変わりましたか?
ジェフオックスベリー

@GeoffOxberry:Java MPIバインディングは存在しますが、10年近く更新されていません。私は彼らの地位が疑わしいと考えています。Fortranには、非常に高速に実行できる多数のI / Oオプションがあります。Parallel HDF5(および一般的にHDF5)を検討することをお勧めします。I / Oが真に支配的である(実行時間の50%以上)場合、より深刻な対策が必要かもしれませんが、そうでなければ、HDFのようなインターフェースの品質と移植性はおそらく価値があります。
ビル・バルト

@BillBarth:確認する必要があります。Fortran I / Oについての私のコメントは、Fortranで入力ファイルパーサーを作成することを勧めたことがある人の視点から来ています。かなりの構造を適用することで可能ですが、Fortranで正規表現パーサーまたはXMLパーサーライブラリを簡単に広く見たことがありません(例を挙げます)。それには十分な理由があります。Fortranを使用しているのは私たちだけです。おそらく、さまざまなユースケースを考えています。
ジェフオックスベリー

2

Aronの非常に包括的な答えに加えて、scicomp.stackexchangeのさまざまなスレッドを調べます。これらのスレッドは、プログラムの速度だけでなく、どのくらい簡単か難しいかという質問の両方を取り上げます。これらの言語でソフトウェアを作成および保守することです。

それは、そこに書かれていることに加えて、いくつかの観察をさせてください:

(i)リストにco-array Fortranを含めます。私の知る限り、実際にそれをサポートするコンパイラの数は非常に少なく、実際、私はゼロです。最も広く利用可能なFortranコンパイラはGNU gfortranであり、現在の開発ソースはco-arrayのサブセットを解析しますが、実際にはそれをサポートしていません(つまり、構文は受け入れますが、セマンティクスは実装していません) 。もちろん、これは新しいFortran規格に関する一般的な観察です:コンパイラが実際に新しい規格をサポートするまでの遅れは数年で測定されます-コンパイラはここ数年でFortran 2003を完全に実装し、Fortran 2008を部分的にしかサポートしていません使用しているものをサポートするコンパイラを使用している場合、これを使用することを止めることはできません。

(ii)同じことがC ++ / Cilk +にも当てはまります。はい、IntelはGCCのブランチでこれを開発していますが、どのGCCリリースでも使用できず、おそらくしばらくは使用できません。少なくとも典型的なLinuxマシンにインストールされたGCCバージョンのCilk +が見つかるまで、少なくとも2〜3年かかると予想できます。

(iii)C ++ / TBBは別の話です:TBBはしばらくの間存在し、非常に安定したインターフェイスを持ち、過去数年間(Linux上でもWindows上でも)存在していたほとんどのC ++コンパイラでコンパイルできます。私たちはすでに数年前から取引でこれを使用してきましたが、すでに良い結果が得られています。それに関する非常に良い本もあります。

(iv)OpenMPに関して私自身の意見があります。つまり、それは問題を探す解決策だということです。これは、非常に規則的なデータ構造がある場合に興味深い内部ループの並列化に適しています。しかし、何かを並列化する必要がある場合、それがやりたいことはめったにありません。本当にやりたいのは外側のループを並列化することだからです。そのため、TBBなどのソリューションは、言語ので(#pragmasを介して)スレッドハンドルにアクセスできない方法で記述することよりもプログラミング言語のメカニズムを使用するため、はるかに優れたソリューションです。 、プログラム内からの結果ステータスインジケータなど。

(v)実験的な場合は、並列プログラミング用に設計された新しいプログラミング言語、特に説明したようなタスクにも注目してください。基本的に、X10Chapelの 2つがあります 。私はチャペルに関する素晴らしいチュートリアルを見てきましたが、それはうまく設計されているように見えますが、もちろん今日は両方とも島の解決策でもあります。


記録のために、Intelは、現在のコンパイラに並列化された(分散メモリ)共配列Fortranが組み込まれていると主張しています。TACCで調査中ですが、まだ報告するものがありません。Crayのコンパイラにも実装がありますが、これは世界中の小さな整数のマシンでのみ利用可能です。共配列に関して完全なFortran 2008標準を実装している人はまだいないと思いますが、いくつかのコンパイラではまだ初期段階のサポート以上のものがあります。もちろん、Cilk +はIntelコンパイラでも使用できますが、おそらく依存することはまだ賢明ではありません。
ビル・バルト

Fortran 2008標準は2010年後半まで承認されなかったため、CAFが広く利用可能になるのは数年前です。G95には実際には(非フリーの)実装がありましたが、もう開発されていません(開発者はPathScaleに参加していました)。
stali

g95のほとんどは最終的にgfortranになりましたが、CAFはその一部ではない可能性があります。
ウルフギャングバンガース

Intelコンパイラーはco-arrayを適切にサポートしていると思います。彼らはmpiexecを使用して構築しました。それは私の最初の選択ではありません。良い点は、同じ実装が共有メモリと分散メモリで実行できることです(いくつかのテストを実行しました)。opteron共有メモリプロセッサが非常にリーズナブルな価格で60コアに達すると、まず共有メモリオプションを確認したいと思います。
ELECTRIQUE

2

一般に、このソフトウェアプロジェクトについて本当に真剣に考えているのであれば、自分が最も快適だと思う言語なら何でも完全に書き直すことを提案します。一人で仕事をしているように思えるので、自宅で最も感じる言語で最高の結果が得られます。

ただし、より具体的には、並列処理に関しては、少し枠を超えて考えてみることをお勧めします。OpenMPには長所がありますが、シーケンシャルコードを取得し、あちこちで並列処理を行うという考え方に固執しています。Intels TBBについても、本質的に同じことが言えます。

Cilkは間違いなく正しい方向への一歩です。つまり、本質的に並列セットアップで問題/解決策を再考することを強制します。しかし、私がそれについて好きではないことは、それがさらに別の言語であるということです。また、並列タスク間の関係を大まかにしか推測できないため、スケジューラは非常に保守的である可能性があり、特定の問題に対してうまくスケーリングできない場合があります。

ただし、実装に真剣に取り組んでいる場合は、Cilkができることを実行できます。たとえば、相互依存タスクのセットとして問題を書き直し、複数のプロセッサ/コア。pthreadを使用するか、OpenMPを誤用してプロセスを生成します。これを行う方法の良い例は、PLASMAライブラリで使用されるQUARKスケジューラーです。性能とCilkの優れた比較をここに示します


提案されたリンクを見てみましょう。比較用紙は非常に素晴らしいです!ありがとう!私はpthreadについて考えていましたが、プログラムをクロスプラットフォームにしたいです。私が知っていることから、pthreadにはWindowsで問題があります(間違っていますか?)。
電気

@ p3tris:pthreadの「p」はPOSIX用であるため、できる限り移植性が高くなっています。プロジェクトなど、pthreads-win32またはcygwinプロジェクト内に、いくつかの準拠Windows実装があります。
ペドロ

stackoverflow.com/q/2797690/801468に基づいて、それを使用するために整理するために必要なものがたくさんあると思います。私はプログラマーではないので、もっとテストされたものに固執したいと思います。
電気

2

上記のコメントではcoarray fortranについてはほとんど議論されていません。現時点では、私の限られた知識では、コンパイラでのcoarrayサポートはおおよそ次のとおりです。

  • Crayには、少なくとも基本的なcoarray機能をサポートするコンパイラがあります。「教育」を目的としたコードを作成するためにこれを使用しましたが、実際のコードをcoarray fortranで作成できると思います。構文と概念はほとんどMPIよりもはるかに単純ですが、いつものようにlotsaトラップがあり、トラップはMPIとは異なります。
  • Intel fortranには、MPIライブラリの上にCoarrayサポートが組み込まれています。おそらくこれにより、理論上のピークパフォーマンスが制限されますが、メトリックは表示されていません。
  • Gfortranはcoarrayをサポートしますが、単一のイメージ(またはMPIで言えば単一のランク)のみです。したがって、gfortran 4.8または4.9がリリースされるまで、実際の並列化は利用できません。

一般に、Coarrayベースのコードを開始する場合は注意が必要です。構文はシンプルで、MPIを使用するFortran / C / C ++よりもはるかに便利ですが、フル機能ではありません。たとえば、MPIは多くのリダクション操作などをサポートしており、非常に便利です。それは本当に多くのコミュニケーションの必要性に依存します。例が必要な場合はお知らせください。ファイルを掘り下げることができれば、いくつかを提供できます。


はい、この種の問題に対するCoarray Fortranの準備状況に関する詳細情報は、確かに役立ちます。scicompへようこそ!
アロンアフマディア

1

Sparkをご覧ください。Sparkは、関数型プログラミングを利用するメモリ内の計算のための分散フレームワークです。Sparkのプログラムの構造はMPIと比較すると非常に異なります。基本的には、メモリ内のデータに関数として自動的に配布される単一のコンピューターのようなコードを記述します。Scala、Java、Pythonをサポートしています。

ロジスティック回帰(スカラ):

//load data to distributed memory
val points = spark.textFile(...).map(parsePoint).cache()
var w = Vector.random(D) // current separating plane
for (i <- 1 to ITERATIONS) {
  val gradient = points.map(p =>
    (1 / (1 + exp(-p.y*(w dot p.x))) - 1) * p.y * p.x
  ).reduce(_ + _)
  w -= gradient
}
println("Final separating plane: " + w)

低レベルの計算にFortranライブラリを使用するMLib(Machine Learning library)と呼ばれる拡張機能があります(Pythonではnumpyが使用されていると思います)。そのため、アイデアは単純で、アルゴリズムに集中し、最適化を低レベル(処理の順序、データの配布など)に任せます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.