2

ある function の 2 つの競合する実装のベンチマークを行いたいとしましょうdouble a(double b, double c)。入力値を取得できる大きなデータが既にあるarray <double, 1000000> valsので、ベンチマークはおおよそ次のようになります。

//start timer here
double r;
for (int i = 0; i < 1000000; i+=2) {
    r = a(vals[i], vals[i+1]);
}
//stop timer here

さて、巧妙なコンパイラは、最後の反復の結果しか使用できず、残りを単純に殺して、double r = a(vals[999998], vals[999999]). もちろん、これはベンチマークの目的に反します。

他のすべての最適化を維持しながら、この種の最適化を防ぐ良い方法 (複数のコンパイラで動作する場合のボーナス ポイント) はありますか?

(空のブロックの挿入に関する他のスレッドを見たことがありますが、インライン化や並べ替えが妨げられるのではないかと心配しています。また、各反復中asmに結果を追加するという考えは特に好きではありません。これは、sum += r;結果のタイミング.この質問の目的のために、他の代替ソリューションに焦点を当てることができれば素晴らしいことですが、これに興味のある人にとっては、コメントで活発な議論があり+=、多くの場合、それが最も適切な方法であるというコンセンサスがあります. . )

4

1 に答える 1

4

a別のコンパイルユニットに入れ、 LTO(リンク時の最適化)を使用しないでください。そのように:

  • ループは常に同一です(に基づく最適化による違いはありませんa
  • 関数呼び出しのオーバーヘッドは常に同じです
  • 純粋なオーバーヘッドを測定し、実装を比較するためのベースラインを作成するには、空のバージョンのベンチマークを実行するだけです。a

aコンパイラは、への呼び出しに副作用がないと想定できないため、ループを最適化して最後の呼び出しだけに置き換えることはできないことに注意してください。


まったく異なるアプローチでは、クロックサイクルを測定するCPUコアのハードウェアレジスタであるRDTSCを使用できます。マイクロベンチマークに役立つ場合もありますが、結果を正しく理解することは簡単ではありません。たとえば、これをチェックして、RDTSCの詳細についてSOをゴーグル/検索してください。

于 2013-03-09T11:18:39.450 に答える