優れたソフトウェア設計で20%のパフォーマンスペナルティ


17

オブジェクト指向プログラミングを最大限に活用する方法を習得する方法として、スパース行列計算用の小さなライブラリを作成しています。パーツ(疎行列と、それらの接続構造を記述するグラフ)が非常に緩やかに結合されている素晴らしいオブジェクトモデルを作成するために、私は一生懸命取り組んできました。私自身の見解では、コードははるかに拡張性があり、保守が容易です。

ただし、鈍いアプローチを使用した場合よりも多少遅くなります。このオブジェクトモデルを使用することのトレードオフをテストするために、基になるグラフのカプセル化を破る新しいスパースマトリックスタイプを作成して、実行速度を確認しました。

最初は、かなり暗いように見えました。私がかつて誇りに思っていたコードは、洗練されたソフトウェア設計のないバージョンよりも60%遅くなりました。しかし、APIをまったく変更せずに、関数をインライン化し、ループを少し変更するという、いくつかの低レベルの最適化を行うことができました。これらの変更により、競合よりもわずか20%遅くなりました。

それは私の質問に私をもたらします:それが私が素晴らしいオブジェクトモデルを持っていることを意味する場合、どのくらいのパフォーマンス損失を受け入れるべきですか?


どのスパース行列演算を測定しましたか?
ビルバース14年

行列ベクトル乗算。行列のサイズはでした。平均次数ランダムグラフのグラフラプラシアンを作成しました。また、一部のマシンでは20%の数値が悪化するため、今ではすべてを捨てる傾向があります。深いため息n=102416384d=ログ2n
ダニエルシェイプロ14年

3
どのプログラミング言語を使用していますか?通常、C ++のようなものを使用すると、低コスト(または実在しない)コストでエレガントな(デザインの)デザインを回避できます。メタプログラミングのない他の言語(Java、Fortranなど)では、20%のコストが妥当と思われます。
LKlevin 14年

コードを見せていただけますか?どの言語を使用しましたか?どのコンパイラとコンパイルフラグですか?パフォーマンスヒットの原因を正確に見つけましたか?どのようにして正しい理由を見つけましたか?どのプロファイラーを使用し、どのように使用しましたか?素敵なオブジェクトモデルが非効率的に実装されていないことは確かですか?20%は十分に小さいため、多くのデータを収集し、詳細な分析を行う必要があります。これは、実装が劣っている、またはその他のコーディングの問題ではなく、設計が原因であると断言できます。
キリル14年

ちょっとした注意:誰もが純粋なパフォーマンスよりも優れたデザインを公に賞賛しているようです(もちろん非常に正当な理由があります)。しかし、それでは、なぜ実際のコードは本当に維持できないのでしょうか?すべてのコードスロブは罪悪感を感じており、したがって公に沈黙していますか?
AlexE 14

回答:


9

設計の優れた原則を理解している科学的ソフトウェア開発者は非常に少ないため、この答えが少々長引けば申し訳ありません。ソフトウェアエンジニアリングの観点から見ると、科学ソフトウェア開発者の目標は、しばしば矛盾する一連の制約を満たすソリューションを設計することです。

スパースマトリックスライブラリの設計に適用される可能性がある、これらの制約の典型的な例を次に示します。

  • 1か月で完了
  • ラップトップおよび複数のワークステーションで正常に実行されます
  • 効率的に実行

科学者は、ソフトウェアエンジニアリングのその他の一般的な要件に徐々に注意を払っています。

  • ドキュメント(ユーザーガイド、チュートリアル、コードコメント)
  • 保守性(バージョン管理、テスト、モジュール設計)
  • 再利用性(モジュール設計、「柔軟性」)

これらの要件のいずれかが必要になる場合があります。Gordon Bellのパフォーマンス賞を獲得しようとしている場合、ほんの数パーセントも関連性があり、あなたのコードの品質を評価する審査員はほとんどいません(あなたが正しいと確信できる限り)。クラスターやスーパーコンピューターなどの共有リソースでこのコードを実行することを正当化しようとする場合、コードのパフォーマンスに関する主張を頻繁に防御する必要がありますが、これらが非常に厳しいことはめったにありません。アプローチのパフォーマンスの向上を説明する論文をジャーナルに掲載しようとする場合、競合他社よりも合法的に高速である必要があります。20%のパフォーマンスは、保守性と再利用性を向上させるためのトレードオフです。

十分な開発時間を与えられた「良いデザイン」という質問に戻って、パフォーマンスを犠牲にすべきではありません。目的が可能な限り高速に実行されるコードを作成することである場合、コードはこれらの制約を考慮して設計する必要があります。コード生成、インラインアセンブリなどの手法を使用したり、高度に調整されたライブラリを利用して問題を解決したりできます。

しかし、十分な開発時間がない場合はどうでしょうか?何がいいの?まあ、それは依存します、そして、誰もこれ以上の文脈なしであなたにこの質問にあなたに良い答えを与えることができそうにないでしょう。

FWIW:高性能のスパースマトリックスカーネルの作成に本当に関心がある場合は、最適化されたPETScインストールと比較し、それらを破っている場合はチームと協力する必要があります。彼らはチューニングされたカーネルをライブラリに喜んで組み込みます。


私はコードジェネレーターに興味があります-それらは私にとって有用かもしれないと思いますが、それらを維持するのが難しいのではないかと心配しています。JavaプログラマーがJavaプログラマーを頻繁に使用することは知っていますが、多くの場合、特定のアプリケーション用のコードを生成するように調整されています。それらを使用する科学的コードを知っていますか?
ダニエルシェイプロ14年

ATLAS、FFTW、Spiral、OSKI、Ignition、stencil_codegenなど。公には宣伝されていませんが、MKLとESSLの重要なカーネルのいくつかがこの方法で生成されたとしても驚かないでしょう。保守可能なカーネル生成コードを書くことは、興味深いフォローアップの質問になります。私はこれを経験しましたが、私は自分を権威とは思わないでしょう。
アロンアフマディア

12

あなたが何に時間を費やしているのかという質問です。私たちのほとんどにとって、プログラミングの3/4の時間と結果を待つ時間の1/4を費やしています。(数値は異なる場合がありますが、数値は完全にメリットがないわけではないと思います。)したがって、2倍の速さ(1.5時間単位ではなく3/4時間単位)でプログラミングできる設計がある場合、パフォーマンスの300%のヒット(1/4から1時間単位)が発生する可能性がありますが、問題の解決に費やされる実際の時間の点ではまだ先に出ています。

一方、高負荷の計算を行っている場合、計算が異なって見える場合があり、コードの最適化により多くの時間を費やすことができます。

私にとっては、生産性が向上した場合、20%はかなり良いトレードオフのように思えます。


良い答えです。パフォーマンスが重要な場合にも重要性を付け加えます。与えられた科学的コードは、行列乗算だけを行っているわけではありません。ランタイムの20%が行列乗算である場合、20%のパフォーマンスヒットは全体で4%の違いしかないので、使いやすいライブラリと引き換えに喜んで受け取ります。
アウレリウス

1
また、ライブラリの記述が適切であれば、バグが少なくなるため、不正確な結果を待つ時間を短縮できます。
Davidmh

4

(何らかの理由で)最大50%のペナルティはそれほど悪くはありません。

実際、コンパイラーのタイプに基づいて、パフォーマンスに0〜30%の違いが見られました。これは、低次のFE離散化から生じる行列に関するPETScのスパースMatMultルーチン用です。


1

ソフトウェア設計は、時間の経過とともに自動的に改善されることはありません。パフォーマンスが向上します。次のCPUで20%を取り戻します。また、優れたソフトウェア設計により、将来ライブラリを簡単に拡張または改善できます。


これが質問に答えるとは思わない。
ニコグアロ

0

一般的な原則は、最初に適切な設計を行い、必要な場合にのみパフォーマンスを最適化することです。20%のパフォーマンスの向上が本当に必要なユースケースは、仮に出てきたとしても、かなりまれです。

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