读书人

memcpy提高效率解决办法

发布时间: 2012-05-02 15:36:04 作者: rapoo

memcpy提高效率
代码如下:

C/C++ code
#include<stdio.h>#include<string.h>#include<time.h>char dest[65536],source[65536];void dumpcopy(){    for(int i=0;i<10000;i++)    for(int i=0;i<65536;++i){        dest[i]=source[i];    }}void smartcopy(){    for(int i=0;i<10000;i++)    memcpy(dest,source,65536);}int main(){    clock_t start,middle,end;    start=clock();    dumpcopy();    middle=clock();    smartcopy();    end=clock();    printf("%.20f\n",(middle-start)/(double)CLOCKS_PER_SEC);//约2.2s    printf("%.20f\n",(end-middle)/(double)CLOCKS_PER_SEC);//约0.07s    return 0;}


测试了下占用CPU时间,大约是2.2s和0.07s
为什么调用memcpy提高了速度,本身memcpy是函数调用,有函数开销,反而性能提高了
<<C 专家编程>>P151 书上原话:
之所以出现性能下降,是因为source和destination的大小正好都是Cache的容量的整数倍,SS2上的Cache并行不是按顺序填充的--它使用一种特殊的算法,填充于同一Cache行的主存地址恰好是该Cache行大小的整数倍,这是因为存储优化引起的--在这种设计方法中,只有地址的高位才被放入标签中,这样一来,source和destination便不可同时出现在cache中,于是导致了性能显著下降。
在这个source和destination都使用同一个Cache行的特殊情况下,会导致每次对内存的引用都无法命中Cache,使CPU利用率大大降低,因为他不得不等待常规操作的内存操作完成。
库函数memcpy()经过特别的优化以提高性能,它把先读取一个Cache行再对它进行写入这个循环分开,这就避免了上述问题。
我没看懂,不吝赐教,先谢谢了

[解决办法]
额……翻译得比较绕口,或者可以说翻译有问题。我也看不明白。

但大意是说:

1.source和destination在默认的存储优化中,是无法共存于Cache中的,每次读写source和destination时,都要去内存中操作,导致了所需时间大大延长。

2.memcpy把source和destination进行了拆分,然后进行循环读写,避免了所谓的存储优化,使得source和destination能共存于Cache中,而不用每次都去内存中进行操作。

这是我的理解,不过最好还是去看看英文原版,这个翻译太扯淡了。
[解决办法]
不知道从哪里翻译出来的,看不懂。

不过可以肯定楼主是在Debug模式下测试的。在我看来,就仅仅是代码效率的差别。memcpy的具体传送在一条指令里完成,而且使用的是SSE指令,传送速度非常快。而直接的数组复制在传送时使用的代码太多(不止是循环语句,那里面还包含着用于调试的很多东西哪),计算速度当然就慢很多了。

经测试,如果采用release版本编译,这两段代码会被译成同样的形式,执行时间相同。
[解决办法]
1 慢的原因是因为,
source和destination 无法同时 从内存 放到cache中,
因此每做一个字符的拷贝,都要
a. 把src 读取到cache中
b cache 到寄存器
c 把dst读取到cache (src已经被覆盖了)
d cache到寄存器
e mov 操作

但是编译器提供的 memcpy
估计是用了 ss2 的指令,
每次可以读取多个字符,然后拷贝多个字符
这样就减少了 从内存到cache的来回操作。

[解决办法]
深入理解计算机系统

第6章, 不必抠字,理解是关键

读书人网 >C语言

热点推荐