Sum*_*uma 7 c++ performance visual-studio-2005 memcpy intrinsics
我想在时间关键函数中复制相对较短的内存序列(小于1 KB,通常为2-200字节).CPU端的最佳代码似乎是rep movsd.但是我不知道怎么能让我的编译器生成这段代码.我希望(我依旧记得这么看)使用memcpy会使用编译器内置的内在函数来做到这一点,但基于反汇编和调试,似乎编译器正在使用调用memcpy/memmove库实现.我也希望编译器可能足够聪明,可以识别以下循环并单独使用rep movsd,但似乎没有.
char *dst;
const char *src;
// ...
for (int r=size; --r>=0; ) *dst++ = *src++;
Run Code Online (Sandbox Code Playgroud)
有没有办法让Visual Studio编译器生成rep movsd序列而不是使用内联汇编?
想到几个问题.
首先,你怎么知道movsd会更快?你有没有查看它的延迟/吞吐量?x86架构充满了不应该使用的旧指令,因为它们在现代CPU上效率不高.
第二,如果你使用std::copy而不是memcpy 会发生什么?std::copy可能更快,因为它可以在特定数据类型的编译时专用.
第三,你是否在项目属性下启用了内部函数 - > C/C++ - >优化?
当然,我假设也启用了其他优化.
同时我发现了什么:
当复制的块大小在编译时已知时,编译器将使用内在函数。如果不是,则调用库实现。当大小已知时,生成的代码非常好,根据大小进行选择。根据需要,它可以是单个 mov、或 movsd、或 movsd 后跟 movsb。
看来,如果我真的想始终使用 movsb 或 movsd,即使使用“动态”大小,我也必须使用内联汇编或特殊内在函数(见下文)。我知道大小“相当短”,但编译器不知道,我无法将其传达给它 - 我什至尝试使用 __assume(size<16),但这还不够。
演示代码,使用“-Ob1(仅内联扩展)进行编译:
#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;
}
Run Code Online (Sandbox Code Playgroud)
我最近发现存在非常简单的方法如何使 Visual Studio 编译器使用 movsd 复制字符 - 非常自然和简单:使用内在函数。以下内在函数可能会派上用场: