計算科学でC ++式テンプレートを使用する必要があるのはいつですか。また、使用しない*場合はありますか?


24

私がC ++で科学的なコードに取り組んでいるとします。同僚との最近の議論では、式テンプレートは本当に悪いことであり、gccの特定のバージョンでのみソフトウェアをコンパイルできる可能性があると主張されました。おそらく、この問題は、このDownfallのパロディの字幕で言及されているように、いくつかの科学的コードに影響を与えています。(これらは私が知っている唯一の例なので、リンクです。)

ただし、SIAM Journal of Scientific Computingのこのペーパーのように、一時変数への中間結果の保存を回避することにより、パフォーマンスの向上をもたらすことができるため、式テンプレートが有用であると主張する人もいます。

C ++でのテンプレートメタプログラミングについてはあまり知りませんが、それが自動微分および区間演算で使用される1つのアプローチであることは知っています。それが式テンプレートについての議論になりました。パフォーマンスの潜在的な利点とメンテナンスの潜在的な欠点の両方(それが正しい言葉である場合)を考えると、計算科学でC ++式テンプレートをいつ使用し、いつ避けるべきですか?


ああ、ビデオは面白すぎる。私はそれが存在することを知りませんでした。誰が作ったのか、知ってる?
ウルフギャングバンガース

わからない。いくつかのPETScの人々からリンクが送られてきました。FEniCS開発者が作成したと思います。
ジェフオックスベリー

ビデオリンクが壊れており、私は好奇心で死にかけています。新しいリンク?
プラキソライト

ああ、なんてことはない、ヒトラーの動画にYouTube が来たのを見
プラキソライト

回答:


17

式テンプレートに関する私の問題は、それらが非常に漏れやすい抽象化であることです。非常に複雑なコードを記述して、より良い構文で簡単なタスクを実行するために多くの作業を費やしています。ただし、アルゴリズムを変更したい場合は、ダーティコードをいじる必要があり、型や構文が足りないと、完全に理解できないエラーメッセージが表示されます。アプリケーションが式テンプレートに基づいたライブラリに完全にマッピングされる場合、検討する価値があるかもしれませんが、よくわからない場合は、通常のコードを書くことをお勧めします。確かに、高レベルのコードはあまりきれいではありませんが、必要なことだけを行うことができます。利点として、コンパイル時間とバイナリサイズが大幅に減少し、コンパイラとコンパイルフラグの選択によるパフォーマンスの大きな変動に対処する必要がなくなります。


ええ、gcc 2.95からgcc 4.xにコードを移植しなければならず、コンパイラーがテンプレートに関するあらゆる種類のエラーを投げていたときに、長いエラーメッセージのいくつかを直接目にしました。私の研究室の仲間は、C ++で区間演算用のテンプレートライブラリを開発しています(より多くの研究を達成するために、Boost :: Intervalにない新しい機能を追加しています)。コンパイルします。
ジェフオックスベリー

12

他の人は、ETプログラムを書くのがどれだけ難しいかという問題と、エラーメッセージを理解する複雑さについてコメントしています。コンパイラーの問題についてコメントさせてください。大きな問題の1つは、C ++標準に完全に準拠し、すべてを機能させ、移植性のあるコンパイラーを見つけることでした。その結果、多くのバグを発見しました。私の名前には、gcc、Intel icc、IBM xlC、およびPortlandのpgiccで配布されている2〜300個のバグレポートがあります。したがって、deal.II構成スクリプトは、主にテンプレート、フレンド宣言、名前空間などの分野での多数のコンパイラバグテストのリポジトリです。

しかし、コンパイラーのメーカーは本当に一緒に行動していることがわかりました。今日、gccとiccは今日すべてのテストに合格しており、2つの間で移植可能なコードを書くのは簡単です。PGIはそれほど遅れてはいないと思いますが、PGIにはいくつかの癖があり、長年にわたって消えないようです。一方、xlCはまったく別の話です-6か月ごとにバグを修正しますが、バグレポートを何年も提出しているにもかかわらず、進捗は非常に遅く、xlCは取り引きをコンパイルできませんでした。

これがすべてを意味するのは、2つの大きなコンパイラーを使い続ければ、今日動作することを期待できます。現在、ほとんどのコンピューターとOSには通常少なくとも1つが搭載されているため、これで十分です。より困難な唯一のプラットフォームはBlueGeneであり、通常システムコンパイラはすべてのバグを含むxlCです。


好奇心から、/ Qで新しいxlcコンパイラに対してコンパイルしようとしましたか?
アロン

いいえ。xlCをあきらめたことは認めます。
ウルフギャングバンガース

5

あなたが言ったように、コンパイラがまだそれらに苦しんでいたとき、私はかなり前にETのを少し実験しました。私のコードでは線形代数に電撃戦のライブラリを使用しました。問題は、優れたコンパイラーを得ることでした。私は完璧なC ++プログラマーではないため、コンパイラーのエラーメッセージを解釈していました。後者は単に管理不能でした。コンパイラは、平均で約1000行のエラーメッセージを生成します。プログラミングエラーをすばやく見つけることができませんでした。

詳細については、Ooonumericsの Webページをご覧ください(2つのETワークショップの議事録があります)。

しかし、私は彼らから遠く離れていたでしょう....


コンパイラのエラーメッセージは確かに私の懸念の1つです。プロジェクト用のライブラリを作成するためにコンパイルしたテンプレート化されたC ++コードの一部を使用すると、コンパイラは数百行の警告メッセージを生成する場合があります。しかし、それは私のコードではなく、私はそれを理解していません。一般的に言って、それは機能するので、そのままにします。長くて不可解なエラーメッセージは、デバッグの前兆にはなりません。
ジェフオックスベリー

4

問題は、「式テンプレート(ET)」という用語ですでに始まっています。正確な定義があるかどうかはわかりません。しかし、その一般的な使用法では、「線形代数式のコーディング方法」と「計算方法」が何らかの形で組み合わされています。例えば:

ベクトル演算をコーディングします

v = 2*x + 3*y + 4*z;                    // (1)

そして、それはループによって計算されます

for (int i=0; i<n; ++i)                 // (2)
    v(i) = 2*x(i) + 3*y(i) + 4*z(i);

私の意見では、これは2つの異なるものであり、分離する必要があります。(1)インターフェイスであり、(2)1つの可能な実装です。これはプログラミングの一般的な方法です。確かに(2)は適切なデフォルトの実装かもしれませんが、一般的には、専用の専用実装を利用できるようにしたいと考えています。たとえば、次のような関数が必要です

myGreatVecSum(alpha, x, beta, y, gamma, z, result);    // (3)

コーディング中に呼び出されます(1)。多分(3)は(2)のようなループを内部的に使用するだけです。ただし、ベクターのサイズによっては、他の実装の方が効率的な場合があります。とにかく、高性能の専門家は可能な限り実装(3)することができます。(1)を(3)の呼び出しにマッピングできない場合は、(1)の構文糖を避けて、すぐに(3)を直接呼び出します。

私が説明するのは新しいことではありません。それどころか、BLAS / LPACKの背後にある考え方です。

  • LAPACKのすべてのパフォーマンスクリティカルな操作は、BLAS関数を呼び出すことによって実行されます。
  • BLASは、一般に必要な線形代数式のインターフェイスを定義するだけです。
  • BLASには、さまざまな最適化された実装が存在します。

BLASのスコープが十分でない場合(たとえば(3)のような機能を提供しない場合)、BLASのスコープを拡張できます。したがって、60年代と70年代のこの恐竜は、石器時代のツールを使用して、インターフェイスと実装を明確かつ直交的に分離しています。(ほとんどの)数値C ++ライブラリがこのレベルのソフトウェア品質を達成しないのは、ちょっとおかしいです。プログラミング言語自体は非常に洗練されていますが。したがって、BLAS / LAPACKがまだ生きており、積極的に開発されていることは驚くことではありません。

したがって、私の意見では、ETはそれ自体悪ではありません。しかし、それらが数値C ++ライブラリで一般的に使用される方法は、科学コンピューティング界で非常に悪い評判を得ました。


マイケル、表現テンプレートのポイントの1つが欠けていると思います。コード例(1)は、実際には最適化されたBLAS呼び出しにマッピングされません。実際、BLASルーチンが存在する場合でも、BLAS関数呼び出しのオーバーヘッドにより、小さなベクトルと行列ではかなりひどくなります。BlazeやEigenのような洗練された式テンプレートライブラリは、一時式の使用を回避するために遅延式評価を使用できますが、ドメイン固有の言語に近いものはほとんど手巻き線形代数に勝るものはないと確信しています。
アロンアフマディア

いいえ、あなたはポイントを逃していると思います。(a)頻繁に必要な線形代数演算の仕様としてのBLAS(b)ATLAS、GotoBLASなどのBLASの実装を区別する必要があります。ところで、FLENSでの動作: デフォルトでは(1)のような式BLASからaxpyを3回呼び出して評価します。ただし、(1)変更せずに、(2)のように評価することもできます。したがって、論理的には次のようになります。(1)のような操作が重要な場合は、指定されたBLAS操作(a)のセットを拡張できます。
マイケルレーン

重要な点は、「v = x + y + z」のような表記法と、最終的にどのように最終的に計算されるかを分離することです。この点で、Eigen、MTL、BLITZ、blaze-libは完全に失敗します。
マイケルレーン

1
正しいですが、頻繁に必要な線形代数演算の数は組み合わせです。C ++のような言語を使用する場合、遅延評価を使用してインテリジェントにサブブロックとアルゴリズムを組み合わせることにより、式テンプレート(これはEigen / Blazeアプローチ)を使用して必要に応じて実装するか、大規模なすべての可能なルーチンのライブラリ。どちらのアプローチも支持しません。NumbaとCythonでの最近の研究が示しているように、Pythonのような高レベルのスクリプト言語でも同様のパフォーマンスを得ることができます。
アロンアーマディア

繰り返しになりますが、私が不満を持っているのは、Eigenのような洗練された(複雑だが柔軟性に欠ける)ライブラリが、表記法と評価メカニズムを密接に結びつけ、それが良いことだとさえ思っているという事実です。Matlabのようなツールを使用する場合は、コードを作成し、Matlabが可能な限り最高のことをしていることを確認したいだけです。C ++のような言語を使用する場合は、制御したいです。デフォルトの評価メカニズムが存在するが、それを変更することが可能でなければならないのであれば感謝します。それ以外の場合は、戻ってC ++の関数を直接呼び出します。
マイケルレーン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.