0

我很好奇为什么该memcpy()功能比简单的手动复制要快。

这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

int main() 
{ 
    clock_t begin, end;
    double time_spent;
    int i, j;   
    char source[65536], destination[65536]; 

    begin = clock();

    for (j = 0; j<1000; j++) 
        for (i = 0; i < 65536; i++) destination[i] = source[i];
    //slower than memcpy(destination, source, 65536);

    end = clock();
    time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
    printf("%Lf\n",time_spent);
    system("pause");
} 

执行memcpy()不做同样的事情吗?提前致谢。

4

7 回答 7

4

memcpy()可以合并各种其他优化,例如 SIMD。有关更多信息,请参阅此答案

于 2013-03-30T22:31:54.190 回答
4

一个好的优化编译器应该确定您的循环实际上是 memmove() 或 memcpy() 并将其替换为对该函数的调用。这仍然留下了一个问题:为什么这样做很聪明?

事实证明,手动优化用于复制内存的已编译代码还有很大的空间,而编译器还不够聪明,无法做到这一切(它也非常特定于 cpu,因此操作系统将有专门的版本用于他们支持的每个 CPU 系列,并在运行时交换它们)。

这是 OSX 的 x86_64 SSE 4.2 复制实现:http ://www.opensource.apple.com/source/Libc/Libc-825.25/x86_64/string/bcopy_sse42.s

于 2013-03-30T22:32:08.280 回答
4

memcpy() 的实现不是做同样的事情吗?

不必要。

这是一个标准库函数,因此:

  • 它可能是高度优化的,使用特定于平台的快速汇编指令,或者它每次迭代只复制一个以上的字节,如果处理器有足够大的寄存器,这会更快;
  • 它可能被编译器识别为内置,因此它可能会执行更多优化步骤,例如,将其内联以消除函数调用开销,或从其上下文中推断出您正在尝试执行的操作并使用其他方法执行,等等.
于 2013-03-30T22:32:14.393 回答
1

因为 for 循环会一一复制项目。而 memcpy() 逐块复制项目。您可以在此处阅读 memcpy() 的源代码:https ://www.student.cs.uwaterloo.ca/~cs350/common/os161-src-html/memcpy_8c-source.html或此处http://research。 microsoft.com/en-us/um/redmond/projects/invisible/src/crt/memcpy.c.htm

于 2013-03-30T22:32:02.817 回答
1

memcpy()将尝试一次复制字,即在 32 位系统上每次迭代 4 个字节,在 64 位系统上每次迭代 8 个字节。

于 2013-03-30T22:32:55.903 回答
0

memcpy不是香草循环。有许多优化。

对齐和字长之类的东西允许memcpy以稳定的速度以更大的块复制内存。

于 2013-03-30T22:32:34.557 回答
0

您可以直接进入memcpy以发现这不是一个简单的循环。

于 2013-03-30T22:35:23.863 回答