四年前写过一篇小内存拷贝优化:http://www.skywind.me/blog/archives/143
纠结了一下还是把全尺寸拷贝优化代码发布出来吧,没啥好保密的,
如今总结一下全尺寸内存拷贝优化的要点:
1. 策略区别:64字节以内用小内存方案,64K以内用中尺寸方案,大于64K用大内存拷贝方案。
2. 查表跳转:拷贝不同小尺寸内存,直接跳转到相应地址解除循环。
3. 目标对齐:64字节以上拷贝的先用普通方法拷贝几个字节让目标地址对齐,好做后面的事情。
4. 矢量拷贝:并行一次性读入N个矢量到 sse2 寄存器,再并行写出。
5. 缓存预取:使用 prefetchnta ,提前预取数据,等到真的要用时数据已经到位。
6. 内存直写:使用 movntdq 来直写内存,避免缓存污染。
部分理论,见论文:《Using Block Prefetch for Optimized Memory Performance》
但论文考虑问题比较单一,所以实际代码写的比论文复杂不少,目前在各个尺寸上基本平均能够加速 40%,比较GCC 4.9, VS2012的 memcpy,不排除未来的 libc, crt库继续完善以后,能够达到下面代码的速度。但我看libc和crt的 memcpy代码已经很久没人更新了,不知道他们还愿意继续优化下去么?
行了,具体实现各位读代码吧,需要 SSE2 指令集支持,gcc编译时需要 –msse2 一下,点击(more)展开代码,测试结果附在源文件最后注释部分: