いくつかのプリミティブな画像処理操作でSIMD命令組み込み関数を使用して実験するときに、パフォーマンスの変化を測定するためのマイクロベンチマークを構築しています。ただし、有用なマイクロベンチマークを作成することは難しいため、最初に、できるだけ多くの変動とエラーの原因を理解する(そして可能であれば排除する)ことを望んでいます。
私が説明しなければならない1つの要因は、測定コード自体のオーバーヘッドです。私はRDTSCで測定しており、次のコードを使用して測定オーバーヘッドを見つけています。
extern inline unsigned long long __attribute__((always_inline)) rdtsc64() {
unsigned int hi, lo;
__asm__ __volatile__(
"xorl %%eax, %%eax\n\t"
"cpuid\n\t"
"rdtsc"
: "=a"(lo), "=d"(hi)
: /* no inputs */
: "rbx", "rcx");
return ((unsigned long long)hi << 32ull) | (unsigned long long)lo;
}
unsigned int find_rdtsc_overhead() {
const int trials = 1000000;
std::vector<unsigned long long> times;
times.resize(trials, 0.0);
for (int i = 0; i < trials; ++i) {
unsigned long long t_begin = rdtsc64();
unsigned long long t_end = rdtsc64();
times[i] = (t_end - t_begin);
}
// print frequencies of cycle counts
}
このコードを実行すると、次のような出力が得られます。
Frequency of occurrence (for 1000000 trials):
234 cycles (counted 28 times)
243 cycles (counted 875703 times)
252 cycles (counted 124194 times)
261 cycles (counted 37 times)
270 cycles (counted 2 times)
693 cycles (counted 1 times)
1611 cycles (counted 1 times)
1665 cycles (counted 1 times)
... (a bunch of larger times each only seen once)
私の質問は次のとおりです。
- 上記のコードによって生成されたサイクルカウントのバイモーダル分布の考えられる原因は何ですか?
- 最速の時間(234サイクル)がほんの数回しか発生しないのはなぜですか?非常に珍しい状況でカウントを減らすことができますか?
さらに詳しい情報
プラットホーム:
- Linux 2.6.32(Ubuntu 10.04)
- g ++ 4.4.3
- Core 2 Duo(E6600); これは一定レートのTSCを持っています。
SpeedStepがオフになっています(プロセッサがパフォーマンスモードに設定され、2.4GHzで実行されています)。「オンデマンド」モードで実行している場合、243サイクルと252サイクルで2つのピークが得られ、360サイクルと369サイクルで2つの(おそらく対応する)ピークが得られます。
sched_setaffinity
プロセスを1つのコアにロックするために使用しています。各コアで順番にテストを実行すると(つまり、コア0にロックして実行し、次にコア1にロックして実行)、234サイクルの最速時間がわずかに発生する傾向があることを除いて、2つのコアで同様の結果が得られます。コア0よりもコア1の方が少ない回数。
コンパイルコマンドは次のとおりです。
g++ -Wall -mssse3 -mtune=core2 -O3 -o test.bin test.cpp
GCCがコアループ用に生成するコードは次のとおりです。
.L105:
#APP
# 27 "test.cpp" 1
xorl %eax, %eax
cpuid
rdtsc
# 0 "" 2
#NO_APP
movl %edx, %ebp
movl %eax, %edi
#APP
# 27 "test.cpp" 1
xorl %eax, %eax
cpuid
rdtsc
# 0 "" 2
#NO_APP
salq $32, %rdx
salq $32, %rbp
mov %eax, %eax
mov %edi, %edi
orq %rax, %rdx
orq %rdi, %rbp
subq %rbp, %rdx
movq %rdx, (%r8,%rsi)
addq $8, %rsi
cmpq $8000000, %rsi
jne .L105