64-bit - memcpy() 性能 - Ubuntu x86_64

标签 64-bit memcpy

我观察到一些我无法解释的奇怪行为。以下是详细信息:-

#include <sched.h>
#include <sys/resource.h>
#include <time.h>
#include <iostream>

void memcpy_test() {
    int size = 32*4;
    char* src = new char[size];
    char* dest = new char[size];
    general_utility::ProcessTimer tmr;
    unsigned int num_cpy = 1024*1024*16; 
    struct timespec start_time__, end_time__;
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start_time__);
    for(unsigned int i=0; i < num_cpy; ++i) {
        __builtin_memcpy(dest, src, size);
    }
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start_time__);
    std::cout << "time = " << (double)(end_time__.tv_nsec - start_time__.tv_nsec)/num_cpy << std::endl;
    delete [] src;
    delete [] dest;
}

当我在编译器选项中指定 -march=native 时,生成的二进制文件运行速度慢 2.7 倍。这是为什么 ?如果有的话,我希望 -march=native 生成​​优化的代码。是否有其他功能可以显示这种类型的行为?

编辑 1:
另一个有趣的一点是,如果 size > 32*4 那么由此生成的二进制文件的运行时间之间没有区别

编辑2:
以下是详细的性能分析(__builtin_memcpy()):-

大小 = 32 * 4,没有 -march=native - 7.5 ns,有 -march=native - 19.3

大小 = 32 * 8,没有 -march=native - 26.3 ns,有 -march=native - 26.5

编辑 3:

即使我分配了 int64_t/int32_t,这个观察结果也不会改变。

编辑 4:

size = 8192,没有-march=native ~ 2750 ns,有-march=native ~ 2750(之前报这个数字有错误,写错了26.5,现在是正确的)

我已经跑了很多次,每次运行的数字都是一致的。

最佳答案

我已将您的发现复制到:g++ (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2 , Linux 2.6.38-10-generic #46-Ubuntu x86_64在我的 Core 2 Duo 上。结果可能会因您的编译器版本和 CPU 而异。我得到 ~26 和 ~9。

When I specify -march=native in compiler options, generated binary runs 2.7 times slower. Why is that ?



因为 -march=native 版本被编译成(使用 objdump -D 发现,你也可以使用 gcc -S -fverbose-asm ):
    rep movsq %ds:(%rsi),%es:(%rdi) ; where rcx = 128 / 8

没有的版本被编译成 16 个加载/存储对,例如:
    mov    0x20(%rbp),%rdx
    mov    %rdx,0x20(%rbx)

这在我们的计算机上显然更快。

If anything, I would expect -march=native to produce optimized code.



在这种情况下,结果证明是悲观的支持 rep movsq在一系列 Action 中,但情况可能并非总是如此。第一个版本较短,在某些(大多数?)情况下可能会更好。或者它可能是优化器中的错误。

Is there other functions which could show this type of behavior ?



指定 -march=native 时生成的代码不同的任何函数, 嫌疑人包括在头文件中实现为宏或静态的函数,其名称以 __builtin 开头.可能还有(浮点)数学函数。

Another interesting point is that if size > 32*4 then there is no difference between the run time of the binaries thus generated



这是因为它们都编译为 rep movsq , 128 可能是 GCC 将生成一系列加载/存储的最大大小(看看这是否也适用于其他平台会很有趣)。顺便说一句,当编译器在编译时不知道大小(例如 int size=atoi(argv[1]); )时,它只会变成对 memcpy 的调用。带或不带开关。

关于64-bit - memcpy() 性能 - Ubuntu x86_64,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6801440/

相关文章:

.net - 如何解决 "%1 is not a valid Win32 application"?

c++ - memcpy() 随机崩溃

c++ - 使用 memcpy 在 C++ 中复制 A-N-D 数组

C 编码::将结构写入内存块

python - 如何让 Python 使用 Assembly

java - 64 位升级后关闭 Tomcat JVM 服务的时间更长

excel - 使用 Excel 2007(Vista 64 位版本)加载 32 位 DLL

c - 不太确定,memcpy 上有段错误吗?

c - 从 void 指针传输值

c++ - 让其 C++ 开发应用程序在 64 位模式下运行有什么大的优势吗?