【问题标题】:Why is memcpy() faster? [duplicate]为什么 memcpy() 更快? [复制]
【发布时间】:2013-03-21 09:24:18
【问题描述】:

我很好奇为什么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() 的实现不是做同样的事情吗? 提前致谢。

【问题讨论】:

  • 你编译时使用了哪些优化标志?

标签: c memcpy


【解决方案1】:

memcpy() 可以合并各种其他优化,例如 SIMD。请参阅this answer 了解更多信息。

【讨论】:

    【解决方案2】:

    因为 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

    【讨论】:

      【解决方案3】:

      一个好的优化编译器应该确定您的循环实际上是 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

      【讨论】:

        【解决方案4】:

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

        不一定。

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

        • 它可能经过高度优化,使用特定于平台的快速汇编指令,或者每次迭代只复制一个以上的字节,如果处理器有足够大的寄存器,则速度会更快;
        • 它可能被编译器识别为内置函数,因此它可能会执行更多优化步骤,例如,将其内联以消除函数调用开销,或从其上下文推断您尝试执行的操作并使用另一个执行方法等。

        【讨论】:

          【解决方案5】:

          memcpy 不是普通循环。有许多优化。

          对齐和字长等因素允许memcpy 以稳定的速度以更大的块复制内存。

          【讨论】:

            【解决方案6】:

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

            【讨论】:

              【解决方案7】:

              您只需进入memcpy 即可发现这不是一个简单的循环。

              【讨论】:

                猜你喜欢
                • 2015-04-21
                • 2012-02-10
                • 2014-06-19
                • 1970-01-01
                • 2011-12-08
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2015-02-02
                相关资源
                最近更新 更多