ライブラリ関数のFLOPカウント


13

単純な関数でFLOPの数を評価するとき、基本的な算術演算子を集計する式を単純にたどることができます。ただし、偶数除算を含む数学ステートメントの場合、これを行うことはできず、加算と乗算のみの関数からのFLOPカウントと比較できると期待されます。操作がライブラリに実装されると、状況はさらに悪化します。したがって、特別な機能のパフォーマンスについて合理的な考えを持つことが不可欠です。

特別な機能とは、次のようなものを意味します。

  • exp()
  • sqrt()
  • sin / cos / tan()

通常はシステムライブラリによって提供されます。

これらの複雑さの決定は、それらの多くが適応性があり、入力依存の複雑さを持っているという事実によってさらに混乱します。たとえば、exp()の数値的に安定した実装は、多くの場合、適応的に再スケーリングしてルックアップを使用します。ここでの私の最初の印象は、この場合にできる最善の方法は、関数の平均的な動作を確認することです。

この議論全体は、もちろん、アーキテクチャに大きく依存しています。この議論では、従来の汎用アーキテクチャに限定し、特別な機能ユニット(GPUなど)を持つアーキテクチャを除外できます。

システムとシステムの比較のために、特定のアーキテクチャ向けにこれらを標準化するかなり簡単な試みを見つけることができますが、メソッドとメソッドのパフォーマンスを重視する場合、これは受け入れられません。これらの関数のフロップの複雑さを決定するためのどの方法論が受け入れられると考えられますか?大きな落とし穴はありますか?


ピーター、簡単なコメント。数学ライブラリによって提供される関数の良い例をいくつか提供しますが、通常、浮動小数点除算は浮動小数点ユニットによって実装されます。
アロンアフマディア

ありがとう!私は十分に明確ではありませんでした。より良いコントラストを提供するために編集しました。
ピーターブルーン

sin、cos、およびsqrtがすべて、x86命令のx87浮動小数点サブセットにも実際に実装されていることを知って驚いた。私はあなたのポイントを得ると思いますが、受け入れられたプラクティスは、わずかに大きな定数を持つ浮動小数点演算としてこれらを扱うことだと思います:)
アロンAhmadia

@AronAhmadia 10年以上にわたってx87を使用する理由はありませんでした。分割しsqrt()てSSE / AVXにありますが、加算や乗算よりもはるかに時間がかかります。また、Sandy Bridge AVXではベクトル化が不十分で、SSE命令の2倍の長さ(半分の幅)が必要です。たとえば、倍精度AVX(4倍幅)は、サイクルごとに8フロップである、パックされた乗算とパックされた加算をすべてのサイクルで実行できます(依存関係やメモリのストールがないと仮定)。これらの「4フロップ」を行うには、20〜44サイクルの除算が必要です。
ジェドブラウン

sqrt()はPowerPCではオプションです。Freescale MPC5xxxシリーズなど、このアーキテクチャの組み込みチップの多くは命令を実装していません。
ダミアン14年

回答:


10

同じ時代遅れの「フロップ」の定義に従ってフロップの数をカウントするのではなく、コードがFPUにどの程度バインドされているか、またはFPUをどれだけ効果的に使用しているかを評価する方法が必要なようです。つまり、すべての浮動小数点ユニットがサイクルごとにフルキャパシティで実行されている場合、同じピークに到達するメトリックが必要です。Intel Sandy Bridgeを見て、これがどのように揺れるかを見てみましょう。

ハードウェアでサポートされている浮動小数点演算

このチップはAVX命令をサポートしているため、レジスタは32バイト長です(4つの倍精度を保持)。スーパースカラーアーキテクチャでは、命令を重複させることができます。ほとんどの算術命令は、新しい命令が次のサイクルで開始できる場合でも、完了するまでに数サイクルかかります。これらのセマンティクスは通常、レイテンシ/逆スループットを記述することで省略されます。5/ 2の値は、命令が完了するのに5サイクルかかることを意味しますが、1サイクルごとに新しい命令を開始できます(オペランドが利用可能で、データがない場合)依存関係とメモリを待っていません)。

コアあたり3つの浮動小数点演算ユニットがありますが、3番目は説明に関係ありません。主な機能は加算と乗算であるため、関連する2つをAおよびMユニットと呼びます。手順の例(Agner Fogの表を参照)

  • vaddpd:パックド加算、1サイクルの間ユニットAを占有、レイテンシー/逆スループットは3/1
  • vmulpd:パックド乗算、ユニットM、5/1
  • vmaxpd:パックドセレクトペアワイズマキシム、ユニットA、3/1
  • vdivpd:パックド除算、ユニットM(および一部のA)、入力に応じて21/20〜45/44
  • vsqrtpd:パックされた平方根、一部のAおよびM、入力に応じて21/21から43/43
  • vrsqrtps:単精度入力用のパックされた低精度逆数平方根(8 floats

重複する可能性がvdivpdありvsqrtpd、明らかに微妙でわかりにくいものの正確なセマンティクスは、どこにも文書化されていません。ほとんどの用途では、オーバーラップの可能性はほとんどないと思いますが、マニュアルの文言では、複数のスレッドがこの命令でオーバーラップの可能性を高める可能性があることを示唆しています。サイクルごとに開始し、サイクルごとに合計8フロップするvaddpdと、フロップのピークに達する可能性がありvmulpdます。密行列-行列乗算(dgemm)は、このピークにかなり近づくことができます。

特別な命令のためにフロップを数えるとき、私はFPUのどれだけが占有されているかを見ます。入力範囲内で、vdivpd完了に平均24サイクルを要し、ユニットMを完全に占有しているが、(使用可能な場合は)加算を半サイクル同時に実行できるとの引数を想定します。FPUは、これらのサイクル中に24個のパックされた乗算と24個のパックされた加算(完全インターリーブvaddpdおよびvmulpdvdivpdを実行できますが、a を使用すると、12個の追加のパック加算ができます。除算を行うための最良の方法がハードウェア(合理的)を使用することであると想定する場合vdivpd、36個の「フロップ」としてカウントし、各スカラー除算を36個の「フロップ」としてカウントする必要があることを示します。

相互平方根を使用すると、特に完全な精度が必要ない場合や、入力範囲が狭い場合に、ハードウェアを破ることができる場合があります。前述のように、vrsqrtps命令は非常に安価であるため、(単精度の場合)vrsqrtps1回実行した後、1回または2回のニュートン反復を実行してクリーンアップできます。これらのニュートン反復は

y *= (3 - x*y*y)*0.5;

これらの操作の多くを実行する必要がある場合、これはの単純な評価よりも大幅に高速になりy = 1/sqrt(x)ます。ハードウェア近似の逆平方根が利用可能になる前は、パフォーマンスに敏感なコードのいくつかは、悪名高い整数演算を使用して、ニュートン反復の初期推定を見つけていました。

ライブラリが提供する数学関数

ライブラリが提供する数学関数に同様のヒューリスティックを適用できます。SSE命令の数を決定するためにプロファイルを作成できますが、これまで説明したように、それはストーリー全体ではなく、特別な機能の評価にすべての時間を費やすプログラムはピークに近づかないように見えるかもしれませんが、そうではありませんすべての時間がFPUの制御外に費やされていることを伝えるのに役立ちません。

ベースラインとして優れたベクトル数学ライブラリを使用することをお勧めします(たとえば、インテルのVML、MKLの一部)。各コールのサイクル数を測定し、そのサイクル数で達成可能なピークフロップを掛けます。そのため、パックされた指数関数の評価に50サイクルかかる場合、100フロップ×レジスタ幅としてカウントします。残念ながら、ベクトル数学ライブラリは呼び出すのが困難な場合があり、すべての特別な機能を備えていないため、スカラー計算を行うことになります。その場合、仮想スカラー指数を100フロップとしてカウントしますサイクルなので、これらの指数関数の評価にすべての時間が費やされた場合にのみ、「ピーク」の25%が得られます。

他の人が述べたように、PAPIまたはさまざまなインターフェイスを使用して、サイクルとハードウェアイベントカウンターをカウントできます。単純なサイクルカウントでrdtscは、インラインアセンブリのスニペットを使用して命令を使用して、サイクルカウンターを直接読み取ることができます。


7

ハードウェアカウンターへのアクセスを許可するPAPIと簡単なテストプログラムを使用して、実際のシステムでカウントできます。私のお気に入りのPAPIインターフェイス/ラッパーはIPM(Integrated Performance Monitor)ですが、他のソリューションもあります(たとえば、TAU)。これにより、かなり安定したメソッド間比較が得られます。


4

あなたが尋ねたかのように私はこの質問に答えるつもりです:

「数値線形代数に由来する従来の乗加算キャリーFLOPカウントの代わりに、特別な機能に大きく依存するアルゴリズムのパフォーマンスを分析的に比較または予測する方法」

私はあなたの最初の前提に同意します、多くの特別な機能のパフォーマンスはアーキテクチャに依存し、これらの各機能は通常一定のコストを持つものとして扱うことができますが、同じサイズの2つのプロセッサ間でも定数のサイズは変化します異なるアーキテクチャを持つ会社(参照用にAgner Fogの命令タイミング表を参照)。

ただし、比較の焦点は個々の浮動小数点演算のコストにあるべきではないことに同意します。FLOPのカウントはある程度有用ですが、2つの潜在的なアルゴリズムを比較する際に、特別な関数のコストがあまり関係しない重要な考慮事項がいくつかあると思います。浮動小数点演算:

  1. スケーラビリティ-並列アーキテクチャで効率的に実装できるタスクを特徴とするアルゴリズムは、近い将来、科学計算の分野を支配します。コミュニケーションの低下、同期の必要性の低下、または自然な負荷バランスの改善など、より優れた「スケーラビリティ」を備えたアルゴリズムは、より低速な特殊機能を採用するため、少数のプロセスでは低速になりますが、最終的にはプロセッサの増加。

  2. 参照の時間的局所性-アルゴリズムはタスク間でデータを再利用するため、プロセッサは不要なメモリトラフィックを回避できますか?アルゴリズムが通過するメモリ階層の各レベルは、各メモリアクセスに(大体)桁違いのコストを追加します。結果として、特別な操作の密度が高いアルゴリズムは、より大きなメモリ領域での単純な関数操作の数が等しいアルゴリズムよりも大幅に高速になる可能性があります。

  3. メモリフットプリント-これは以前のポイントと強く関係していますが、コンピューターが大きくなるにつれて、コアあたりのメモリ量は実際に減少傾向にあります。小さなメモリフットプリントには2つの利点があります。1つ目は、少量のプログラムデータがプロセッサキャッシュ内に完全に収まる可能性が高いことです。2つ目は、非常に大きな問題の場合、メモリフットプリントの小さいアルゴリズムがプロセッサメモリに収まり、コンピュータの能力を超える問題を解決できることです。


FLOPS / secを知ることで、どのボトルネック体制(メモリ、通信)をかなりうまく分離できるかを主張します。たとえば、多くの時間をmatvecsに費やしているNewton-Krylovメソッドを検討してください。Matvecsは、マトリックスエントリごとにFLOPまたは2つを実行します。組み立てられていないスムーザーは、より良い結果をもたらす可能性があります。Jedと私もこれについて話していましたが、別の概念は、FLOPにバインドされた計算にどれだけのサイクルを費やしているかを確認することです。ただし、これには非常に詳細な監視が必要な場合があり、合計FLOPS /秒​​がより実用的です。
ピーターブルーン

アロンは、この答えのほとんどは、この他の質問に答えるの賛成でピーターの質問を回避するようだ:scicomp.stackexchange.com/questions/114
ジェッド・ブラウン

@JedBrown、私は同意します、もっとしっかりした答えをまとめるのに時間を割いてくれてありがとう。
アロンアフマディア

0

フロップを数えるのはなぜですか?すべての操作のサイクルをカウントするだけで、普遍的なものが得られます。

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