我想要复制一个相对较短的序列的存储器(小于1KB,通常为2-200字节),在一次重要的功能。最好的代码这CPU面似乎是 rep movsd.但是我总不能让我的编译器,来产生这个代码。我希望(和我依稀记得看到那)使用memcpy会做这个编译器使用的内置内部函数,而是基于拆装和调试这似乎编译器的使用呼叫memcpy/memmove图书馆实施,而不是。我还希望编译可能是足够的智慧认识到以下环路,并使用 rep movsd 在其自己的,但它似乎没有。

char *dst;
const char *src;
// ...
for (int r=size; --r>=0; ) *dst++ = *src++;

是否有某种方式使Visual Studio编译器生成 rep movsd 序列,使用内联会?

有帮助吗?

解决方案 3

使用memcpy用恒定的尺寸

我找到了什么同时:

编译器将使用的固有当复制块的大小编制时所周知的。当它不是呼吁图书馆执行。当尺寸是已知的,该代码生成的是非常好的,基于选择大小。它可以是一个单一的传,或movsd,或movsd随后通过movsb,如需要。

看来,如果我真的想要使用movsb或movsd既往,甚至是一个"动态"的大小我将必须使用内联会或特征(见下文)。我知道大小是"较短",但编译器不知道这和我无法沟通,这给它的-我们甚至试图使用__假设(大小<16),但它是不够的。

演示码、汇编与"-Ob1(扩大对联only):

  #include <memory.h>

  void MemCpyTest(void *tgt, const void *src, size_t size)
  {
    memcpy(tgt,src,size);
  }

  template <int size>
  void MemCpyTestT(void *tgt, const void *src)
  {
    memcpy(tgt,src,size);
  }

  int main ( int argc, char **argv )
  {
    int src;
    int dst;
    MemCpyTest(&dst,&src,sizeof(dst));
    MemCpyTestT<sizeof(dst)>(&dst,&src);
    return 0;
  }

专门的内部函数

我发现最近有存在的非常简单的方法如何使Visual Studio编译器复制人物使用movsd-非常自然的和简单的:使用内部函数。下面的内部函数可能来方便:

其他提示

若干问题浮现在脑海中。

首先,你怎么知道MOVSD会更快?你有没有抬头其延迟/吞吐量? X86架构是完全的,因为他们只是没有现代CPU的效率非常高,不应该使用这些混沌旧指令。

第二,如果你使用std::copy代替了memcpy会发生什么? std::copy是潜在地更快,因为它可以在编译时被专用于特定的数据类型。

和第三,你有没有启用内部函数在项目属性 - > C / C ++ - >优化

当然我假定其他优化是使能的。

您运行的是优化的建立?除非优化是它不会使用固有的。它也是值得注意的,它可能会使用比代表MOVSD更好的复制循环。它应该尝试使用MMX,至少,在一次副本上执行64位。其实6年或7年后,我写了MMX优化复制循环做这样的事情。不幸的是,编译器的内在的memcpy约1%跑赢我MMX副本。这真的教我不要做什么编译器正在做的假设。

让你定时的memcpy?在最近的版本的Visual Studio中,memcpy的实现使用SSE2 ......这应该是比rep movsd更快。如果复制块为1 KB,那么它是不是真的那么编译器不使用固有由于时间的函数调用相比,时间副本将被忽略的问题。

请注意,为了使用movsdsrc必须指向对准以32位边界存储器和它的长度必须是4个字节的倍数。

如果是这样,为什么你的代码中使用char *代替int *什么?如果不是的话,你的问题是没有实际意义。

如果你改变char *int *,你的可能的从std::copy得到更好的结果。

编辑:?有你测定该复制是瓶颈

使用的memcpy。此问题已经得到解决。

FYI代表MOVSD并非总是最好的,代表MOVSB可以更快在一些情况下,并用SSE等最好是MOVNTQ [EDI],XMM0。甚至可以进一步优化大量的存储器中使用页局部性通过移动数据到缓冲器,然后将其移动到目的地。

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