关于循环展开优化的讨论
/*
联系我: jsblcg@163.com
这段代码用于测试循环展开的性能,结果非常奇怪:
如果禁止编译器优化,循环展开如同一般文章所说,展开的越多性能越好,
但如果打开编译器优化(Visual C++ 6),则小于某一尺寸(256K)的数据,
循环读展开没有多大影响,大于这个尺寸的值,展开2层即可,更多的展开
不会提高多少性能
更奇怪的是循环写展开反而性能下降!
数据如下(单位是时钟周期)
机器是P4 1.0G/256M
Windows 2000 Professional
Visual C++ 6.0
禁止优化时
读:
23358907 没有展开
19442372 展开2,有提高
18489986 展开4,提高不明显
17593574 展开8
写:
21410474 有提高
19782066
19475123
19970877
打开最大速度优化:
小数据时(数据意义同上):
699698 影响不大
629779
668786
584814
142500 性能降低了!
571348
611947
675471
大数据时:
15888915
8841968 有提高
8353201
8093060
10166389 性能降低!!
19531106
20007260
19489649
谁能告诉我为什么如此?
*/
#include "stdafx.h"
#include<windows.h>
__int64 GetCounter();
void WriteTest();
void ReadTest();
#define SIZE 1024*1024
int a[SIZE];
int main(int argc, char* argv[])
{
ReadTest();
printf( "\n" );
WriteTest();
return 0;
}
void WriteTest()
{
int k;
for( k=0; k<sizeof(a)/sizeof(int); k++ )
a[k] = 0;
__int64 t1 = GetCounter();
for( k=0; k<sizeof(a)/sizeof(int); k++ )
{
a[k] = 0;
}
__int64 t2 = GetCounter();
Sleep(1000);
printf( "%I64d\n", t2 - t1 );
t1 = GetCounter();
for( k=0; k<sizeof(a)/sizeof(int); k+=2 )
{
a[k] = 0;
a[k+1] = 0;
}
t2 = GetCounter();
Sleep(1000);
printf( "%I64d\n", t2 - t1 );
t1 = GetCounter();
for( k=0; k<sizeof(a)/sizeof(int); k+=4 )
{
a[k] = 0;
a[k+1] = 0;
a[k+2] = 0;
a[k+3] = 0;
}
t2 = GetCounter();
Sleep(1000);
printf( "%I64d\n", t2 - t1 );
t1 = GetCounter();
for( k=0; k<sizeof(a)/sizeof(int); k+=8 )
{
a[k] = 0;
a[k+1] = 0;
a[k+2] = 0;
a[k+3] = 0;
a[k+4] = 0;
a[k+5] = 0;
a[k+6] = 0;
a[k+7] = 0;
}
t2 = GetCounter();
Sleep(1000);
printf( "%I64d\n", t2 - t1 );
}
void ReadTest()
{
int k, d = 0;
for( k=0; k<sizeof(a)/sizeof(int); k++ )
a[k] = 0;
__int64 t1 = GetCounter();
for( k=0; k<sizeof(a)/sizeof(int); k++ )
{
d += a[k];
}
__int64 t2 = GetCounter();
Sleep(1000);
printf( "%I64d\n", t2 - t1 );
t1 = GetCounter();
for( k=0; k<sizeof(a)/sizeof(int); k+=2 )
{
d += a[k];
d += a[k+1];
}
t2 = GetCounter();
Sleep(1000);
printf( "%I64d\n", t2 - t1 );
t1 = GetCounter();
for( k=0; k<sizeof(a)/sizeof(int); k+=4 )
{
d += a[k];
d += a[k+1];
d += a[k+2];
d += a[k+3];
}
t2 = GetCounter();
Sleep(1000);
printf( "%I64d\n", t2 - t1 );
t1 = GetCounter();
for( k=0; k<sizeof(a)/sizeof(int); k+=8 )
{
d += a[k];
d += a[k+1];
d += a[k+2];
d += a[k+3];
d += a[k+4];
d += a[k+5];
d += a[k+6];
d += a[k+7];
}
t2 = GetCounter();
Sleep(1000);
printf( "%I64d\n", t2 - t1 );
}
__declspec(naked)__int64 GetCounter()
{
__asm rdtsc
__asm ret
}