我做的像处理在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对于你所提到的特征集合)它应产生相当最佳特定体系结构的内联代码

我倒是基准,看看什么出来。

张贴由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是不是瓶颈和调整,代码将仅作小的改进。

如果具体到英特尔处理器,你可能会从 IPP 受益。如果你知道它会与Nvidia的GPU上运行也许你可以使用 CUDA - 在这两个情况下,它可能会更好看不是优化的memcpy宽() - 它们提供了在更高层次上提高你的算法的机会。他们都是然而在特定的硬件依赖

如果你在窗,使用 Api,其中有特定的 GPU优化的程序对图形处理(如何快速的可能?你的CPU是不是装载。做些别的事情而GPU力嚼)。

如果你想要OS不可知的,试试 照片.

不要乱动汇编,因为它是所有也可能你会失败惨遭到超过10年的熟练的图书馆制作的软件工程师。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top