很快memcpy用于图像处理?
-
19-09-2019 - |
题
我做的像处理在C,需要复制大块大块的数据存储器的来源和目的地不重叠。
什么是绝对最快的方式做到这一x86平台上使用 海湾合作委员会 (在那里 SSE,SSE2但不SSE3提供)?
我期望的解决方案,无论是在组装或使用的海湾合作委员会内部函数?
我发现下面的链接,但不知道它是否是最好的方法(提交人还说,它有一些错误): http://coding.derkeiler.com/Archive/Assembler/comp.lang.asm.x86/2006-02/msg00123.html
编辑:注意一个复制是必要的,我不能得到周围具有以复制的数据(我可以解释为什么,但我会饶你的解释:))
解决方案
的陈伟霆和谷歌提供。比在Microsoft Visual Studio 2005中的memcpy快30-70%。
void X_aligned_memcpy_sse2(void* dest, const void* src, const unsigned long size)
{
__asm
{
mov esi, src; //src pointer
mov edi, dest; //dest pointer
mov ebx, size; //ebx is our counter
shr ebx, 7; //divide by 128 (8 * 128bit registers)
loop_copy:
prefetchnta 128[ESI]; //SSE2 prefetch
prefetchnta 160[ESI];
prefetchnta 192[ESI];
prefetchnta 224[ESI];
movdqa xmm0, 0[ESI]; //move data from src to registers
movdqa xmm1, 16[ESI];
movdqa xmm2, 32[ESI];
movdqa xmm3, 48[ESI];
movdqa xmm4, 64[ESI];
movdqa xmm5, 80[ESI];
movdqa xmm6, 96[ESI];
movdqa xmm7, 112[ESI];
movntdq 0[EDI], xmm0; //move data from registers to dest
movntdq 16[EDI], xmm1;
movntdq 32[EDI], xmm2;
movntdq 48[EDI], xmm3;
movntdq 64[EDI], xmm4;
movntdq 80[EDI], xmm5;
movntdq 96[EDI], xmm6;
movntdq 112[EDI], xmm7;
add esi, 128;
add edi, 128;
dec ebx;
jnz loop_copy; //loop please
loop_copy_end:
}
}
您可能能够优化其进一步根据您的具体情况,你可以做任何假设。
您可能还需要检查出的memcpy源(memcpy.asm)并去掉其特例处理。它可能会进一步优化!
其他提示
目前或以上-O1
的任何优化级别,GCC将使用内建定义为像memcpy
功能 - 与右-march
参数(-march=pentium4
对于你所提到的特征集合)它应产生相当最佳特定体系结构的内联代码。 p>
我倒是基准,看看什么出来。
张贴由hapalibashi的SSE-代码是去的方式。
如果您需要更高的性能,并且不从编写设备驱动程序的漫长而曲折的道路避而远之:所有的重要平台现在有一个DMA控制器,它能够做一个拷贝作业速度更快,在并行到CPU代码可以做的。
这涉及虽然写入的驱动器。没有大的操作系统,我知道暴露了这个功能,用户侧因安全隐患。
但是,它可能是值得的(如果你需要的性能),因为地球上没有代码能胜过一个硬件是专门做这样的工作。
这个问题是四岁现在我有点惊讶没有人已经提到过存储器的带宽。CPU-Z的报告,我的机器已经PC3-10700RAM。RAM有一个峰值带宽(又名的速率传输,吞吐量等)的10700兆字节/秒。在我的机器上是一个i5-2430M CPU,与高峰涡轮增压频率的3GHz。
从理论上说,有一个无限的快速CPU和我RAM、memcpy可以去 5300兆字节/秒, ,即一半的10700因为memcpy有读然后写信给RAM。(编辑:作为诉oddou指出的那样,这是一个简单的近似)。
另一方面,想象我们有无限的快速RAM和一个现实的CPU,我们能实现吗?让我们使用我的3GHz CPU作为一个例子。如果它可以做一个32位读和32位编写每个周期,则它可能转移3e9*4= 12000兆字节/秒.这一似乎很容易地在达到一个现代化的CPU。目前,我们可以看到,上运行的代码CPU是不是真正的瓶颈。这是其中一个原因,现代化的机器有数据的高速缓存。
我们可以衡量什么CPU真的可以做到的基准memcpy当我们知道数据是缓存。这样做的确是繁琐。我做了一个简单的应用程序,撰写了随机数字阵列,memcpy会到另一个阵列,然后checksumed复制的数据。我走过代码在调试器,以确保聪明的编译器没有删除的副本。改变阵列大小的改变高速缓存的性能-小型阵列适合在高速缓存,大小如此。我得到了以下结果:
- 40字节的数组:16000兆字节/秒
- 400千字节阵列:11000兆字节/秒
- 4000字节的数组:3100兆字节/秒
显然,我的CPU可以阅读和书写的超过32位的每个周期,由于16000超过12000我的理论计算上面。这意味着CPU是更少的一个瓶颈比我已经想法。我用Visual Studio2005年,进入标准memcpy执行情况,我可以看到,它使用的movqda指令关于我的机器。我猜这可以阅读和写64位,每个周期。
好的代码hapalibashi贴实现了4200兆字节/秒在我的机器中约40%的速度比VS2005年执行。我想这是速度更快,因为它使用取的指令,以提高高速缓存的性能。
在摘要,代码上运行的CPU是不是瓶颈和调整,代码将仅作小的改进。