C++ C++;指针复制循环的编译器优化
我在godbolt.org上用-O2编译了这段代码,编译器并没有使用一些memcpy对其进行优化,而是诚实地运行循环C++ C++;指针复制循环的编译器优化,c++,performance,loops,optimization,compiler-optimization,C++,Performance,Loops,Optimization,Compiler Optimization,我在godbolt.org上用-O2编译了这段代码,编译器并没有使用一些memcpy对其进行优化,而是诚实地运行循环 void foo(int* dst, int* src, int n) { for (int i = 0; i < n; ++i) { dst[i] = src[i]; } } void foo(int*dst,int*src,int-n) { 对于(int i=0;i /Cord>关键字,告诉编译器两个范围不会重叠,但是C++没有
void foo(int* dst, int* src, int n)
{
for (int i = 0; i < n; ++i)
{
dst[i] = src[i];
}
}
void foo(int*dst,int*src,int-n)
{
对于(int i=0;i
但如果我将“=src[I]”替换为“=0”,它们将使用memset。但同样,当我用“=1”替换它时,它们运行一个循环。当要设置的值不是零时,为什么要避免memcpy和memset?我认为这是他们将执行的第一批优化之一。由
src
和dest
指向的范围可能重叠,在这种情况下,memcpy
的行为将是未定义的。因此,将此函数优化为只调用memcpy
是不合适的
memmove
是合适的,但是当src
和dest
范围重叠时,它的行为与您的函数不同。考虑以下事项:
int arr[5] = {1, 2, 3, 4, 5};
foo(arr + 1, arr, 4);
调用后,函数将导致arr
包含{1,1,1,1,1}
,而memmove
被指定为导致arr
包含{1,1,2,3,4}
。因此,编译器也无法优化foo
调用memmove
C在C99中添加了
memset
以字节粒度工作,您使用的int
通常超过1个字节(4个字节)。这就是为什么编译器不能轻松地用memset替换赋值=1
还要注意的是,
-O2
并没有为GCC启用矢量化,尽管它显然为Clang启用了矢量化-ftree矢量化(包含在-O3
中)是GCC生成更快的SIMD指令所必需的(速度不如memcpy
/memmove
/memset
在许多平台上的速度)。两种g++
和clang++
似乎都在优化std::copy\n(src,n,dst)代码>更好(这是您无论如何都应该使用的)我认为memcpy
永远不会与该函数签名一起使用。如果数组重叠,memcpy
将导致UBmemmove
更有可能。使用template void foo(int(&dst)[N],int(&src)[N]){{for(unsigned i=0;i
您可以通过clang++
和rep movsq
获得memcpy