4

開発ボード(ZC702)でZynqチップを使用しています。これは667MHzのデュアルcortex-A9 MPCoreを備え、Linuxカーネル3.3が付属しています。プログラムの実行時間を比較したかったので、最初にclock_gettimeを使用し、次にARMのコプロセッサによって提供されるカウンタ。カウンタは、1プロセッササイクルごとに増分します。(stackoverflowとこれに関するこの質問に基づく)

-O0フラグを使用してプログラムをコンパイルします(並べ替えや最適化を実行したくないため)

パフォーマンスカウンターで測定する時間は、583833498(サイクル)/ 666.666687 MHz = 875750.221(マイクロ秒)です。

clock_gettime()(REALTIMEまたはMONOTONICまたはMONOTONIC_RAWのいずれか)を使用している場合、測定される時間は 731627.126(マイクロ秒)で、150000マイクロ秒少なくなります。

なぜこれが起こっているのか誰かが私に説明できますか?なぜ違いがあるのですか?プロセッサはクロックスケールしませんが、clock_gettimeで測定される実行時間を短縮するにはどうすればよいですか?以下にサンプルコードがあります。


#define RUNS 50000000
#define BENCHMARK(val) \
__asm__  __volatile__("mov r4, %1\n\t" \
                 "mov r5, #0\n\t" \
                 "1:\n\t"\
                 "add r5,r5,r4\n\t"\
                 "mov r4 ,r4  \n\t" \
                 "mov r4 ,r4  \n\t" \
                 "mov r4 ,r4  \n\t" \
                 "mov r4 ,r4  \n\t" \
                 "mov r4 ,r4  \n\t" \
                 "mov r4 ,r4  \n\t" \
                 "mov r4 ,r4  \n\t" \
                 "mov r4 ,r4  \n\t" \
                 "mov r4 ,r4  \n\t" \
                 "mov r4 ,r4  \n\t" \
                 "sub r4,r4,#1\n\t" \
                 "cmp r4, #0\n\t" \
                 "bne 1b\n\t" \
                 "mov %0 ,r5  \n\t" \
                 :"=r" (val) \
                 : "r" (RUNS) \
                 : "r4","r5" \
        );
clock_gettime(CLOCK_MONOTONIC_RAW,&start);
__asm__ __volatile__ ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(start_cycles));
for(index=0;index<5;index++)
{
    BENCHMARK(i);
}
__asm__ __volatile__ ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(end_cycles));
clock_gettime(CLOCK_MONOTONIC_RAW,&stop);
4

2 に答える 2

4

私は解決策を見つけました。プラットフォームをLinuxカーネル3.3.0から3.5にアップグレードしましたが、その値はパフォーマンスカウンターの値と似ています。どうやら、3.3.0のクロックカウンターの周波数は、CPU周波数の半分ではなく、それが何であるか(約400 MHz)よりも高いと想定されています。おそらく古いバージョンの移植エラーです。

于 2012-11-26T10:31:23.350 に答える
0

POSIXクロックは、で取得できる特定の精度で動作しますclock_getres。その150,000usの差が許容誤差の内側または外側にあるかどうかを確認します。

いずれにせよ、それは問題ではありません。ベンチマークを5回ではなく、1000回以上繰り返す必要があります。次に、次のような単一のベンチマーク実行のタイミングを取得できます。

((end + e1) - (start + e0)) / 1000、 また

(end - start) / 1000 + (e1 - e0) / 1000

e1e0が小さな定数によって制限される誤差項である場合、最大測定誤差は、abs (e1 - e0) / 1000になります。これは、ループの数が増えるにつれて無視できるようになります。

于 2012-11-20T13:52:38.697 に答える