C ++テンプレートを使用した汎用およびメタプログラミングは、計算科学でどの程度有用ですか?


17

C ++言語は、テンプレートを介して汎用プログラミングメタプログラミングを提供します。これらの手法は、多くの大規模な科学計算パッケージ(MPQCLAMMPSCGALTrilinosなど)に組み込まれています。しかし、全体的な開発時間と同等または適切な効率のための使いやすさの点で、CやFortranのような非汎用、非メタ言語を超える価値で、科学計算に実際に貢献したものは何ですか?

科学的な計算タスクを考えると、C ++テンプレートを介した汎用およびメタプログラミングは、よく知られているベンチマーク(コード行、人の努力など)によって測定される生産性、表現力、または使いやすさの向上を実証しましたか?それに対応して、ジェネリックおよびメタプログラミング用のC ++テンプレートの使用にはどのようなリスクが伴いますか?


この質問は意見に対してあまりにも開かれているのではないかと心配していますが、コミュニティの人々が何を言っているのかを見たいです。
ジェフオックスベリー

1
コメントの脱線を完全に削除しました。チャットやメタに再投稿したい場合は、喜んでそうします。ここで私のメタを参照してください
アロンアーマディア

3
また、式テンプレートを使用するタイミングと回避するタイミングに関するアドバイスについては、関連する質問を参照してください
アロンアフマディア

LAMMPSがテンプレートまたはメタプログラミングを使用していると言うのは正しいとは思いません。LAMMPSは、ほとんどの場合Fortranによく似たオブジェクト指向コードです。MPQCにもテンプレートはあまりないと思いますが、非常にオブジェクト指向で多形的です。
ジェフ

1
OpenFOAMは、テンプレートやC ++の他の機能を多用しています
ドンジョー

回答:


14

概して、テンプレートメタプログラミングは実際には使用できないことがわかっています。コンパイルの速度が遅すぎ、エラーメッセージを解読することは不可能です。メタプログラミングを使用する場合、新参者の参入障壁も非常に高くなります。

もちろん、Trilinos、deal.II(私自身のライブラリ)、DUNE、および他の多くのライブラリで見られるように、ジェネリックプログラミングはまったく異なる問題です-異なるデータ型で動作する同じ概念を表現するのは簡単で、コミュニティは、メタプログラミングの問題を回避する範囲内にある限り、大部分を受け入れています。ジェネリックプログラミングは明らかな成功と見なされると思います。

もちろん、これらのトピックはどちらもすぐにOOPに接続されません。繰り返しになりますが、OOPは科学コンピューティングコミュニティに広く受け入れられています。汎用プログラミングよりもさらに、議論のトピックではありません。過去15年間に書かれたすべての成功したライブラリ(C ++、C、またはFortranで書かれたもの)はすべてOOPテクニックを使用します。


4
tmpは初心者ユーザーにとっては難しいかもしれませんが、多くの場合、ライブラリ内で非常にうまく行われます。本当にコードの量を減らすことができますが、実際に何をしているのかを知る必要があるテクニックの1つです。信じられない場合は、EigenまたはElementalのソースを読んでください。テンプレートがなければ美しいコードはほとんど不可能です。
アテレル

5
確かに、それは価値のあるテクニックです。しかし、維持するのは難しく、外部インターフェイスにさらされている場合は使用するのが難しいことがよくあります。そうは言っても、TMPが当初期待されていた成功ではなかった理由の1つは、コンパイラが非常に優れたものになったためだと思います。TMPは、コンパイル時に多くのことがわかっているという事実に基づいており、定数として実際のコードに伝播できます。しかし、コンパイラーはインライン化、関数の複製などに非常に優れているため、今日では「通常の」プログラミングを使用して利点の大部分を得ることができます。
ウルフギャングバンガース

15

経験に基づいた例を挙げましょう。私が日常的に使用するほとんどのライブラリは、何らかの形でOOPを使用しています。OOPは多くのドメインに必要な複雑さを隠すことができますが、パフォーマンスを実際に支援するメカニズムではありません。起こりうることは、ライブラリがオブジェクト階層に基づいて特定の最適化を使用できることですが、ほとんどの場合、複雑さをユーザーから隠すことです。デザインパターンを調べてください。これらは、この複雑さを隠すためによく使用されるメカニズムです。

例としてPETScを取り上げます。PETScは、OOPのインスペクター/エグゼキューターモデルを使用します。このモデルでは、アルゴリズムのいずれかが、特定のオブジェクトで使用可能なルーチンを調べ、ルーチンを達成するために実行するものを選択します。これにより、ユーザーは懸念事項を分離することができます。たとえば、マトリックスアクションには、あらゆる種類のブロックまたは最適化されたルーチンを含めることができ、多数の反復ソルバーで効果的に使用できます。ユーザーが独自のデータ型と評価を指定できるようにすることで、いくつかの重要なルーチンを高速化し、ライブラリ全体の機能を引き続き利用できるようにします。

もう1つの例として、FEniCSとdeal.IIがあります。これらのライブラリはどちらもOOPを使用して、多数の有限要素法を一般化します。要素の種類、要素の順序、直交表現など、すべてが交換可能です。これらのライブラリはどちらも、特定の目的の構造化FEMコードよりも「低速」ですが、FEMの複雑さの多くはユーザーに知られておらず、さまざまな問題を解決できます。

私の最後の例はElementalです。Elementalは、MPIコミュニケーターとデータの場所の管理の難しさを非常に単純な言語構造にした新しい高密度線形代数ライブラリです。その結果、FLAMEシリアルコードがある場合は、データ型を変更することで、Elementalを介してパラレルコードを使用することもできます。さらに興味深いのは、他の分布と同じ分布を設定することで、データ分布を試すことができることです。

OOPは、手作業のアセンブリと競合するためのパラダイムではなく、複雑さを管理する方法と考えるべきです。また、適切に行わないとオーバーヘッドが大きくなるため、タイミングを維持し、使用するメカニズムを更新する必要があります。


3

OOP科学計算で言語機能が行うことは、コードをよりコンパクトに理解して使用するのに役立つ、よりコンパクトなコードステートメントを作成することです。たとえば、FFTルーチンは関数呼び出しごとに多数の引数を保持する必要があるため、コードが煩雑になります。

moduleor classステートメントを使用すると、呼び出し時に必要なものだけを渡すことができます。残りの引数は問題のセットアップ(つまり、配列のサイズと係数)に関係するためです。

私の経験でSUBROUTINEは、55個の引数(in&out)を使用した呼び出しがあり、それを5に減らしてコードを改善しました。

それが価値です。


3

私は、科学計算のための汎用プログラミングとメタプログラミングの強力な擁護者です。私は実際、Feel ++(http://www.feelpp.org)と呼ばれるこれらの手法に基づいて、着実に勢いを得ているGalerkinメソッド用のフリーソフトウェアC ++ライブラリを開発しています。コンパイル時間が遅いなどの困難がまだあることと、舞台裏で何が起こっているのかを理解したい場合、学習曲線が急になる可能性があることは事実です。しかし、これは非常に興味深いことであり、驚くべきことです。ライブラリレベルで実行し、ドメイン固有の言語の背後にある複雑さを隠すと、非常に強力なツールが得られます。使用および比較する方法は非常に広範囲です。科学的コンピューティングの教育目的のために、これは、研究および新しい数値的方法のために、大規模なアプリケーションのために、素晴らしいです、私たちはそれに取り組んでいますが、これまでのところこれまでのところ、私たちはすでにいくつかの素晴らしいことをすることができます。エンジニア、物理学者、数学者がそれを使用しています。彼らのほとんどは、変分定式化のために言語を使用しているだけで、満足しています。私たちの物理学者の同僚が操作するいくつかの定式化を見ると、変分定式化を記述するための高級言語なしで「手作業」で行われるのを見たくありません。私は個人的に、これらの「技術」または「パラダイム」は、コードサイズを巨大な係数で乗算する必要がある科学計算コードの複雑さに取り組むために必要であると考えています。おそらくC ++でのメタプログラミングのサポートを改善する必要がありますが、特にC ++ 11以降、すでに良好な状態にあります。


2

あなたの質問に関連する論文http://arxiv.org/abs/1104.1729を見つけるかもしれません。式テンプレート(科学コードで使用されるテンプレートメタプログラミングの特定のアプリケーション)をパフォーマンスの観点から説明します。


その論文は私を狂気に駆り立てます。最速のプレーンFortranをMKLと比較すると、同様に失われます。手作業で調整されたアセンブリは、人が望んでいるものではありません。ナノ秒ごとにカウントし、非常に多くの人々が再利用できるときに行うことです。
-aterrel

@aterrel:これはまさに私が考えているコントラストです。開発の最終段階として手作業での最適化を行う必要があることを知って、最終段階の前に使用するベースとしてどの言語を選択しますか?どの言語を選択するかを提案するためのハードデータはありますか?
デスブレス

9
@Deathbreath:他のいくつかのスレッドでも同様の回答を繰り返します。概して、コードの最後の速度を調整することはめったにしないことです。ただし、常に高レベルのアルゴリズムをプログラミングします。そのため、大きな作業を迅速に行える言語を選択してください。何らかの方法で低レベルのものを含める方法は常にありますが、プログラミング言語の選択を決定するものであってはなりません。
ウォルフガングバンガース

0

テンプレートは、実行時にタイプ/ドメインチェックを削除するのに非常に優れています。これらはコンパイル時に処理できます。理論的には、実行時にのみタイプチェックを実行できるCまたはFortranの同じタイプの実装よりもパフォーマンスを向上させることができます。チェックはソースコードに実装されます。ただし、Cでもプリコンパイラオプションを使用して同じ結果を得ることができますが、テンプレートとは異なり、これらは手動で行う必要があります。

ただし、テンプレートもかなりのオーバーヘッドを生じる可能性があります。多くの場合、命令キャッシュの使用に影響を与える可能性のあるコードの膨張を引き起こす可能性があります。さらに、一般的なアプローチは、最適化中にコンパイラを妨害することがよくあります-一般的なアプローチを使用する場合、コード分析が必ずしも簡単ではありません。コンパイラーの最適化を含む自動化には常に問題があります-非常に多くの場合、出力コードはキャッシュフレンドリーではありません。

タイプ/ドメインチェックの利点は、確かに安全ではありますが、パフォーマンスの観点から私が見ることができる唯一の本当の利点であり、これらは通常は感知できません。しかし、私が言っているように、全体的な効果はあなたが何をしているかに応じてマイナスになる可能性があります。そのため、多くの場合、重大なボトルネックがあるコードを手作業で最適化する方が適切です。

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