私の考えは、命令キャッシュの制限の影響を示すエレガントなコード例を提供することでした。私は、テンプレートメタプログラミングを使用して、大量の同一機能を作成する以下のコードを書いた。命令キャッシュの制限の影響を実証する方法
volatile int checksum;
void (*funcs[MAX_FUNCS])(void);
template <unsigned t>
__attribute__ ((noinline)) static void work(void) { ++checksum; }
template <unsigned t>
static void create(void) { funcs[t - 1] = &work<t - 1>; create<t - 1>(); }
template <> void create<0>(void) { }
int main()
{
create<MAX_FUNCS>();
for (unsigned range = 1; range <= MAX_FUNCS; range *= 2)
{
checksum = 0;
for (unsigned i = 0; i < WORKLOAD; ++i)
{
funcs[i % range]();
}
}
return 0;
}
外部ループは、ジャンプテーブルを使用して呼び出されるさまざまな関数の量を変化させます。各ループパスに対して、WORKLOAD
関数を呼び出すために要した時間が測定されます。今、結果は何ですか?次の図は、使用された範囲に対する関数呼び出しあたりの平均実行時間を示しています。青色の線は、Core i7マシンで測定されたデータを示しています。赤線で示した比較測定は、Pentium 4マシンで行った。しかし、それは、これらの行を解釈することになると、私は何とか苦労しているように見える...
範囲内のすべての機能のための総メモリ消費量を超え場所を正確に区分的に一定赤い曲線の唯一のジャンプが起こりますテストされたマシン上の1つのキャッシュ・レベルの容量。専用の命令キャッシュはありません。ただし、非常に小さい範囲(この場合は4未満)では、機能の量によって実行時間が増加します。これは分岐予測の効率に関係するかもしれませんが、この場合は関数呼び出しが無条件のジャンプに減少するため、ブランチングのペナルティがあるかどうかはわかりません。
青いカーブは、まったく異なる動作をします。ランタイムは小領域では一定であり、その後は対数を増加させる。しかし、より広い範囲については、曲線は一定の漸近線に再び近づいていると思われる。両方の曲線の質的差異はどのくらい正確に説明できますか?
私は現在、GCC MinGW Win32 x86 v.4.8.1とg++ -std=c++11 -ftemplate-depth=65536
を使用しており、コンパイラの最適化は行っていません。
ご協力いただければ幸いです。私はまた、実験そのものをどのように改善するかについてのアイデアにも興味があります。前もって感謝します!