15

INLINEたとえば、関数にプラグマを追加した場合の効果を比較する基準を使用して、一部のコードを最適化しようとしています。しかし、再コンパイル/実行間で結果が一貫していないことがわかりました。

結果を比較できるように実行全体で一貫した結果を得る方法、またはベンチマークが信頼できるかどうかを評価する方法、つまり (推測) 分散に関する詳細を解釈する方法を知る必要があります。クロックコール」など

私の特定のケースの詳細

これは、上記の私の主な質問とは直交していますが、私の特定のケースでは、いくつかのことが矛盾を引き起こしている可能性があります。

  1. この例で使用する方法が機能しなかったため、使用してIOアクションのベンチマークを試みています。whnfIOwhnf

  2. 私のコードは同時実行を使用しています

  3. たくさんのタブとがらくたを開いてしまった

出力例

これらは両方とも、まったく同じ方法でコンパイルされた同じコードからのものです。すぐ下で最初の実行を行い、変更を加えて別のベンチマークを実行し、元に戻して最初のコードを再度実行し、次のようにコンパイルしました。

ghc --make -fforce-recomp -threaded -O2 Benchmark.hs

ファーストラン:

estimating clock resolution...                                      
mean is 16.97297 us (40001 iterations)                              
found 6222 outliers among 39999 samples (15.6%)                     
  6055 (15.1%) high severe                                          
estimating cost of a clock call...                                  
mean is 1.838749 us (49 iterations)                                 
found 8 outliers among 49 samples (16.3%)                           
  3 (6.1%) high mild                                                
  5 (10.2%) high severe                                             

benchmarking actors/insert 1000, query 1000                         
collecting 100 samples, 1 iterations each, in estimated 12.66122 s  
mean: 110.8566 ms, lb 108.4353 ms, ub 113.6627 ms, ci 0.950         
std dev: 13.41726 ms, lb 11.58487 ms, ub 16.25262 ms, ci 0.950      
found 2 outliers among 100 samples (2.0%)                           
  2 (2.0%) high mild                                                
variance introduced by outliers: 85.211%                            
variance is severely inflated by outliers                           

benchmarking actors/insert 1000, query 100000                       
collecting 100 samples, 1 iterations each, in estimated 945.5325 s  
mean: 9.319406 s, lb 9.152310 s, ub 9.412688 s, ci 0.950            
std dev: 624.8493 ms, lb 385.4364 ms, ub 956.7049 ms, ci 0.950      
found 6 outliers among 100 samples (6.0%)                           
  3 (3.0%) low severe                                               
  1 (1.0%) high severe                                              
variance introduced by outliers: 62.576%                            
variance is severely inflated by outliers

2 回目の実行、約 3 倍遅い:

estimating clock resolution...
mean is 51.46815 us (10001 iterations)
found 203 outliers among 9999 samples (2.0%)
  117 (1.2%) high severe
estimating cost of a clock call...
mean is 4.615408 us (18 iterations)
found 4 outliers among 18 samples (22.2%)
  4 (22.2%) high severe

benchmarking actors/insert 1000, query 1000
collecting 100 samples, 1 iterations each, in estimated 38.39478 s
mean: 302.4651 ms, lb 295.9046 ms, ub 309.5958 ms, ci 0.950
std dev: 35.12913 ms, lb 31.35431 ms, ub 42.20590 ms, ci 0.950
found 1 outliers among 100 samples (1.0%)
variance introduced by outliers: 84.163%
variance is severely inflated by outliers

benchmarking actors/insert 1000, query 100000
collecting 100 samples, 1 iterations each, in estimated 2644.987 s
mean: 27.71277 s, lb 26.95914 s, ub 28.97871 s, ci 0.950
std dev: 4.893489 s, lb 3.373838 s, ub 7.302145 s, ci 0.950
found 21 outliers among 100 samples (21.0%)
  4 (4.0%) low severe
  3 (3.0%) low mild
  3 (3.0%) high mild
  11 (11.0%) high severe
variance introduced by outliers: 92.567%
variance is severely inflated by outliers

「クロック呼び出しの推定コスト」でスケーリングすると、2 つのベンチマークがかなり近いことがわかります。比較のために実数を取得するために私がすべきことは何ですか?

4

2 に答える 2

14

すべての問題を特定するには十分な情報がここにあるわけではありませんが、役立つかもしれないいくつかの提案があります。

Criterion 結果の解釈

外れ値として識別されたサンプルの問題は、それらがジャンク データであるために外れ値であるか、または何らかの正当な理由で異なる有効なデータであるかを、基準が実際に判断できないことです。それらがジャンクであることを強く示唆している可能性があります (「分散が大幅に膨らんでいます」という行) が、これが実際に意味することは、テスト環境、テスト、またはアプリケーション自体を調査して、外れ値の原因を特定する必要があるということです。この場合、システム負荷が原因であることがほぼ確実です (提供された他の情報に基づく)。

BOS の基準の発表を読むことに興味があるかもしれません。これは、基準がどのように機能するかをより詳細に説明し、システム負荷がベンチマーク プロセスにどのように影響するかを正確に示すいくつかの例を示しています。

「クロックコールの推定コスト」の違いに非常に疑問を感じています。(両方の実行で) 外れ値の割合が高く、それらの外れ値には「非常に深刻な」影響があることに注意してください。これは、ピックアップされたクロックタイミング基準がジャンクであり (おそらく両方の実行で)、他のすべてが信頼できないことを意味すると解釈します。@DanielFischerが示唆するように、他のアプリケーションを閉じるとこの問題が解決する場合があります。最悪の場合、ハードウェアの問題である可能性があります。他のすべてのアプリケーションを閉じてもクロック タイミングが信頼できない場合は、別のシステムでテストすることをお勧めします。

同じシステムで複数のテストを実行している場合、クロックのタイミングとコストは実行ごとにかなり一貫している必要があります。そうでない場合は、何かがタイミングに影響を与えているため、データが信頼できません。

それとは別に、要因になる可能性のある2つのランダムなアイデアを次に示します.

CPU負荷

スレッド化されたランタイムは、CPU 負荷の影響を受けやすい場合があります。システムに大きな負荷がかかっていない限り、デフォルトの RTS 値は多くのアプリケーションでうまく機能します。問題は、ガベージ コレクターにいくつかのクリティカル セクションがあることです。そのため、Haskell ランタイムのリソースが不足している場合 (CPU やメモリを他のアプリケーションと競合しているため)、それらのセクションを待機するためにすべての進行がブロックされる可能性があります。これがパフォーマンスに 2.5 倍の影響を与えるのを見てきました。これは、ご覧の 3 倍の違いとほぼ一致しています。

ガベージ コレクターに問題がない場合でも、他のアプリケーションからの CPU 負荷が高いと結果がゆがむため、可能であれば排除する必要があります。

診断方法

  • またはその他のシステム ユーティリティを使用topして、CPU 負荷をチェックします。
  • で実行し+RTS -sます。統計の下部で、これらの行を探します

-RTS -s 出力

gc_alloc_block_sync: 0
whitehole_spin: 0
gen[0].sync: 0
gen[1].sync: 0

ゼロ以外の値は、ガベージ コレクターでのリソースの競合を示します。ここでの大きな値は、重大な問題を示しています。

直し方

  • 他のアプリケーションを閉じる
  • 実行可能ファイルがすべてのコアより少ない数のコアを使用するように指定します (例:+RTS -N6または+RTS -N78 コア ボックス)。
  • 並列ガベージ コレクションを無効にします ( を使用+RTS -qg)。私は通常、並列コレクターを無効にするよりも空きコアを残しておく方が良い結果が得られましたが、YMMV.

入出力

ベンチマークしている関数が何らかの種類の I/O (ディスク、ネットワークなど) を実行している場合は、結果の解釈方法に細心の注意を払う必要があります。ディスク I/O により、パフォーマンスが大幅に変化する可能性があります。100 サンプルに対して同じ関数を実行すると、最初の実行後に I/O がコントローラーによってキャッシュされる可能性があります。または、実行の間に別のファイルにアクセスした場合は、ヘッド シークを実行する必要がある場合があります。他の I/O は通常、これ以上優れているわけではありません。

診断方法

  • 関数が I/O を実行しているかどうかは、おそらくすでにわかっているはずです。
  • のようなツールは、lsof謎の I/O パフォーマンスを追跡するのに役立ちます

直し方

  • I/O をモックします。RAM ディスクを作成します。実際にハードドライブなどに行く以外のこと.
  • 実際の I/O 操作をベンチマークする必要がある場合は、他のアプリケーションからの干渉を最小限に抑えてください。おそらく専用ドライブを使用してください。他のアプリを閉じます。必ず複数のサンプルを収集し、それらの間の差異に注意してください。
于 2012-07-30T15:17:42.270 に答える