�@�拥倪B�m�y��在有 Hardware Prefetcher 下�K�]有�k法真的�y出你�A期中的�Y果 在前面的循�h中 Prefetcher 已��暖好�C了 �K且部份�Y料也存在 Cache 中 �е箩崦娲嫒」����^大的部份反而�绦��r�g�^短的�F象 ��然上面提到的部份只是一��可能的原因, ���H上��需要考量到 Out-of-order execution 及 branch prediction 等等不同�C制的交互作用 因此�绦兴俣入y以由程式�绦械闹噶��的��硗��y 另外附上在我�C器上�绦械��r�g: (Intel(R) Core(TM) i7-2620M) 1, 47570681, 1 2, 34476895, 2 3, 32805033, 4 4, 32431996, 8 5, 32569370, 16 6, 30123933, 32 7, 19037866, 64 8, 8754664, 128 9, 3824499, 256 10, 1959867, 512 11, 1053159, 1024 Ref: [1] Software and Hardware-Based Prefetching http://www.ecs.umass.edu/ece/andras/courses/ECE668/Mylectures/Prefetching-lecture.ppt [2] http://www.tomshardware.tw/305,review-305-7.html 2013/7/30 秦�� <love.infly@xxxxxxxxx> > Hi, 吴伟 > > 之前自己的问题是集中于两个汇编代码不同带来的性能不同的原因。 > > 主要是O0代码在SIZE次循环和SIZE/2次循环的开销是2:1,但是O1代码的开销接近1:1 > 。自己手动改.s的对比结果可以看出来,O0性能差距的原因基本就是在多出来的几个movq上。但是自己不明白原因,所以提问。 > > > > 对于你说的测试结果不一致,我又在自己电脑上做了一次。另外在别人的虚拟机上也简单测了下,和我的结果是一样的。以下是我在本机做的1000次的运行,这个貌似牵扯的比较多,从CPU型号到Gcc版本都会影响结果。 > > ===================================== > > 我用的如下代码运行了1000遍,每次输出基本没有差距(正负1%左右)。所以整体也符合之前的情况,我的机器环境是Xubuntu13.04, > gcc 版本 4.7.3 (Ubuntu/Linaro 4.7.3-1ubuntu1) ,CPU 是Intel(R) Core(TM) > i3-2100 CPU @ 3.10GHz。 > > O0情况下依然是K=1,K=2和K=4的情况下都是1/2递减的。 > O1情况下1/2递减现象消失了,K=1只是稍微多耗时一点, 这个应该确实是循环数不同计算量不同的原因。 > > 代码如下: > > #include <stdio.h> > #include <time.h> > #include <stdint.h> > #define SIZE 64*1024*1024 > #define MAX_K 1024 > int32_t arr [SIZE]; > struct timespec ts; > > int main(int argc, char *argv[]) > { > long i,j= 0; > long start; > long start_sec; > int count = 1; > // init the arr; > for (i = 0; i < SIZE; ++i){ > arr[i] = 0; > } > for (j = 1; j <= MAX_K; count++, j*= 2){ > clock_gettime(CLOCK_REALTIME, &ts); > start = ts.tv_nsec; > start_sec = ts.tv_sec; > for (i = 0; i< SIZE; i+=j){ > arr[i] *=3; > } > clock_gettime(CLOCK_REALTIME, &ts); > printf ("%d, %ld, %ld\n", > count,(ts.tv_sec-start_sec)*1000000000+(ts.tv_nsec -start), j); > } > return 0; > } > > > 另,我还又用下面的相同循环数的代码分别用O0~3运行了几次,结果是K=128之前一直都是递增的,特别的是O1之后,明显的可以看出,初期的几个递增就是2倍递增,比O0的结果更加符合期望结果,数据如下, > **为什么K=128后的时间下降了,我也不清楚原因。** > > 1, 60962944, 1 > 2, 121961343, 2 > 3, 248836377, 4 > 4, 478276479, 8 > 5, 961089972, 16 > 6, 1371127716, 32 > 7, 1851929390, 64 > 8, 964310614, 128 > 9, 994438045, 256 > 10, 1030341734, 512 > 11, 1124689492, 1024 > > 循环数相同的代码就是我贴在SO上的,如下: > > #include <stdio.h> > #include <time.h> > #include <stdint.h> > #define SIZE 64*1024*1024 > int32_t arr [SIZE]; > struct timespec ts; > > int main(int argc, char *argv[]) > { > long i,j= 0; > long start; > long start_sec; > int count = 1; > int k = 0; > > // init the arr; > for (i = 0; i< 64*1024*1024;++i){ > arr[i] = 0; > } > > for (j = 1; j< 1025;){ > clock_gettime(CLOCK_REALTIME, &ts); > start = ts.tv_nsec; > start_sec = ts.tv_sec; > for (i = 0, k = 0; i< 64*1024*1024; i++, k+=j){ > k = k & (SIZE -1); > arr[k] *=3; > arr[k] =1; > } > clock_gettime(CLOCK_REALTIME, &ts); > printf ("%d, %ld, %ld\n", > count,(ts.tv_sec-start_sec)*1000000000+(ts.tv_nsec -start), j); > count++; > j *= 2; > } > return 0; > } > > > 谢谢。 > > > 2013/7/29 Wei WU(吴伟) <wuwei.gucas@xxxxxxxxx>: > > Hi 秦��: > > > > 我对于 CPU Caching > > > 不是很熟悉,没有看出来其中的原因。我自己运行了一下你贴在SO上的程序,得到的测试数据跟你的测试结果并不一致:在O1优化下j=2的时间是j=1的两倍,而在O0的情况下,两者的得分是类似的。 > > > > > 另外,一次运行的数据是不稳定的,确实有时候会出现j=2比j=1还快一点的情况。但是这可能是机器的噪音。建议运行多次(例如1000次)之后得到两者差值的平均,这样分析起来比较可靠。 > > > > 现代CPU的性能分析是一件很困难的事情,如果你有了答案,强烈欢迎你贴在这个邮件列表中,大家共同学习 :-) > > > > 在 2013年7月29日下午4:51,秦�� <love.infly@xxxxxxxxx>写道: > > > >> c代码本身很简单 > >> for (i = 0; i< SIZE; i+=j){ > >> arr[i] *=3; > >> } > >> > >> 就是以一个步进值j遍历整个数组,对成员做*3操作。 > >> > >> O0的代码,步进的值在-24(%rbp)中: > >> > >> movq $0, -32(%rbp) > >> jmp .L5 > >> .L6: > >> movq -32(%rbp), %rax > >> movl arr(,%rax,4), %edx > >> movl %edx, %eax > >> addl %eax, %eax > >> addl %eax, %edx > >> movq -32(%rbp), %rax > >> movl %edx, arr(,%rax,4) > >> movq -24(%rbp), %rax > >> addq %rax, -32(%rbp) > >> .L5: > >> cmpq $67108863, -32(%rbp) > >> > >> O1的代码,步进的值在 %rbx中: > >> > >> movl $0, %eax > >> .L3: > >> movl arr(,%rax,4), %ecx > >> leal (%rcx,%rcx,2), %edx > >> movl %edx, arr(,%rax,4) > >> addq %rbx, %rax > >> cmpq $67108863, %rax > >> jle .L3 > >> > >> > >> 想问的问题是,在O0情况下,j = 1的时间是j=2时间的两倍,O1下,两者就基本接近了,甚至步进为1的还快点,为什么? > >> > >> > >> 问题来源是: > http://stackoverflow.com/questions/17914782/why-cache-doesnt-work-as-it-supposed-to-be/17915086#17915086 > >> > >> 我自己改改O0的代码,变成如下: > >> > >> movq $0, -32(%rbp) > >> movl $0, %eax > >> movq -24(%rbp), %rbx > >> jmp .L5 > >> .L6: > >> movl arr(,%rax,4), %edx > >> movl %edx, %ecx > >> addl %ecx, %ecx > >> addl %ecx, %edx > >> movl %edx, arr(,%rax,4) > >> addq %rbx, %rax > >> .L5: > >> cmpq $67108863, %rax > >> jle .L6 > >> > >> 就和O1差不多了。 > >> > >> 但是不明白,循环里改掉了几个movq,怎么j = 1的速度就和j = 2的差不多了?原因是什么? > >> > >> 谢谢了。 > > > > > > > > > > -- > > 吴伟/Wei Wu > > wuwei.gucas@xxxxxxxxx >