#include <windows.h>
double PCFreq = 0.0;
__int64 CounterStart = 0;
void StartCounter()
{
LARGE_INTEGER li;
if(!QueryPerformanceFrequency(&li))
cout << "QueryPerformanceFrequency failed!\n";
PCFreq = double(li.QuadPart)/1000.0;
QueryPerformanceCounter(&li);
CounterStart = li.QuadPart;
}
double GetCounter()
{
LARGE_INTEGER li;
QueryPerformanceCounter(&li);
return double(li.QuadPart-CounterStart)/PCFreq;
}
int main()
{
StartCounter();
int i,j;
static int x[4000][4000];
#if 1 //Version 1
for (i = 0; i < 4000; i++)
{
for (j = 0; j < 4000; j++)
{
x[j][i] = i + j;
}
}
#else //Version 2
for (j = 0; j < 4000; j++)
{
for (i = 0; i < 4000; i++)
{
x[j][i] = i + j;
}
}
#endif
cout << GetCounter() <<"\n";
return 0;
}
Win7-32ビットマシンのVS2012で上記のコードを試しました。
バージョン 1 の実行時間は 0.200 秒で、バージョン 2 の実行時間は 0.071 秒です。
配列はメモリの連続した領域であり、C++ は配列を行優先方式で格納します。配列内の要素を要求すると、OS はおそらくその要素を含むメモリ ページをキャッシュに取り込みます。ただし、次のいくつかの要素もそのページにあるため (連続しているため)、次のアクセスはすでにVersion-1 のキャッシュに入っています。
したがって、バージョン 1 は高速でなければなりません。
しかし、結果は、バージョン 2 が高速であることを示しています。
結果が矛盾する理由を説明してください。