3

C/C++ コードをベンチマークしたいと考えています。CPU時間、壁時間、サイクル/バイトを測定したい。いくつかの測定関数を作成しましたが、サイクル/バイトに問題があります。

CPU 時間を取得するために、 で関数getrusage()を書きました。RUSAGE_SELFclock_gettimeMONOTONICrdtsc

1024: などのサイズの入力バッファを処理しますchar buffer[1024]。ベンチマークの方法:

  1. ウォームアップ フェーズを実行し、単純にfun2measure(args)1000 回呼び出します。

for(int i=0; i<1000; i++) fun2measure(args);

  1. 次に、ウォール タイムのリアルタイム ベンチマークを実行します。

    `unsigned long i; 倍の時間かかりました。double timeTotal = 3.0; // 3 秒処理

    for (timeTaken=(double)0, i=0; timeTaken <= timeTotal; timeTaken = walltime(1), i++) fun2measure(args); `

  2. CPU時間については(ほぼ同じ):

    for (timeTaken=(double)0, i=0; timeTaken <= timeTotal; timeTaken = walltime(1), i++) fun2measure(args);

しかし、関数の CPU サイクル カウントを取得する場合は、次のコードを使用します。

`unsigned long s = cyclecount();
    for (timeTaken=(double)0, i=0; timeTaken <= timeTotal; timeTaken = walltime(1), i++)
    {
        fun2measure(args);
    }
    unsigned long e = cyclecount();

unsigned long s = cyclecount();
    for (timeTaken=(double)0, i=0; timeTaken <= timeTotal; timeTaken = cputime(1), i++)
    {
        fun2measure(args);
    }
    unsigned long e = cyclecount();`

次に、サイクル/バイトをカウントします((e - s) / (i * inputsSize);inputsSizeの長さなので、ここでは 1024bufferです。しかし、totalTime10 秒に上昇すると、奇妙な結果が得られます。

10 秒間:

Did fun2measure 1148531 times in 10.00 seconds for 1024 bytes, 0 cycles/byte [CPU]
Did fun2measure 1000221 times in 10.00 seconds for 1024 bytes, 3.000000 cycles/byte [WALL]

5 秒間:

Did fun2measure 578476 times in 5.00 seconds for 1024 bytes, 0 cycles/byte [CPU]
Did fun2measure 499542 times in 5.00 seconds for 1024 bytes, 7.000000 cycles/byte [WALL]

4 秒間:

Did fun2measure 456828 times in 4.00 seconds for 1024 bytes, 4 cycles/byte [CPU]
Did fun2measure 396612 times in 4.00 seconds for 1024 bytes, 3.000000 cycles/byte [WALL]

私の質問:

  1. それらの結果は大丈夫ですか?
  2. 時間を増やすと、CPU で常に 0 サイクル/バイトになるのはなぜですか?
  3. このようなベンチマークの平均時間、平均、標準偏差などの統計を測定するにはどうすればよいですか?
  4. 私のベンチマーク方法は 100% 大丈夫ですか?

乾杯!

1回目の編集:

に変更iした後double

Did fun2measure 1138164.00 times in 10.00 seconds for 1024 bytes, 0.410739 cycles/byte [CPU]
Did fun2measure 999849.00 times in 10.00 seconds for 1024 bytes, 3.382036 cycles/byte [WALL]

私の結果は大丈夫のようです。したがって、質問#2はもう質問ではありません:)

4

1 に答える 1

1

あなたの cyclecount ベンチマークには、walltime/cputime 関数呼び出しのコストが含まれているため、欠陥があります。ただし、一般的には、車輪の再発明を試みるのではなく、適切なプロファイラーを使用することを強くお勧めします。特にパフォーマンス カウンターは、信頼できる数値を提供します。また、CPU は通常一定の周波数で実行されていないか、カーネルがタスク スイッチを実行してしばらくアプリを停止する可能性があるため、サイクルは非常に信頼できないことに注意してください。

私は個人的に、特定の関数を N 回実行するようにベンチマークを作成します。N は、十分なサンプルを取得するのに十分な大きさです。外部的には、Linux perf などのプロファイラーを適用して、推論するのに難しい数値を取得します。一定時間ベンチマークを繰り返すと、stddev/avg 値を計算できます。これは、ベンチマークを数回実行し、プロファイラーの出力を評価するスクリプトで実行できます。

于 2013-08-08T17:55:08.570 に答える