1

我注意到memcpy在 Linux 上比在相同硬件上的 Windows 上更快。我使用 Intel i7 4770 CPU 和 16Gb RAM 双启动相同的机器并运行相同的编译 C++ 代码。我正在尝试 memccpy使用此代码

#include <iostream>
#include <chrono>
#include <cstring>

typedef std::chrono::high_resolution_clock Clock;

int main() {
    const int mb = 300;
    int size = mb * 1024 * 1024 / sizeof(int);
    auto buffer = new int[size];
    srand(1);

    for(int i = 0; i < size; i++) {
        auto r = abs(rand()) % 2048;
        buffer[i] = std::max<int>(r, 1);
    }

    auto buffer2 = new int[size];

    const int repeats = 100;
    for (int j = 2; j < mb; j+=2) {
        auto start = Clock::now();

        // Copy j Mb
        int size = j * 1024 * 1024 / sizeof(int);
        for (int i = 0; i < repeats; i++) {
            int offset = 0;
            while (offset < size) {
                // Run memcpy on random sizes
                int copySize = buffer[offset];
                memcpy(buffer2, buffer, copySize * sizeof(int));
                offset += copySize;
            }
        }

        auto end = Clock::now();
        auto diff = std::chrono::duration_cast<std::chrono::nanoseconds>(end-start).count();
        // Time taken per 1Mb
        std::cout << j << "," << diff / j / repeats  << std::endl;
    }
}

Linux 执行速度平均快 10%。在 Linux 上平均需要 20 微秒/Mb,在 Windows 上平均需要 22 微秒/Mb。它在两种情况下都使用 gcc 10.2m64 -O3 -mavx标志编译。我正在从事的项目是 OS 数据库,在那里我看到了更大的影响 memcpy 和 memset 在 Linux 上更快,在小缓冲区的随机长度副本上加速了大约 30%。

知道为什么memcpy在 Windows 上与 Linux 不同吗?我希望它memcpy是用汇编语言编写的,不依赖于操作系统,而只依赖于 CPU 架构。

4

1 回答 1

3

memcpy是标准 C 库的一部分,因此由运行代码的操作系统提供(如果您使用不同的 libc,则由替代提供程序提供)。对于已知大小的小副本,GCC 往往会内联这些操作,因为它通常可以避免函数调用的开销,但对于大的或未知的大小,它往往会使用系统函数。

在这种情况下,您会看到 glibc 和 Windows 有不同的实现,而 glibc 提供了更好的选择。glibc 确实根据给定 CPU 的最佳性能在不同平台上提供了几种不同的变体,但 Windows 可能不会这样做,或者可能具有不太优化的实现。

过去,glibc 甚至利用了memcpy在某些 CPU 上不能有重叠参数并向后复制的事实,但不幸的是,它破坏了一些不符合标准的程序,尤其是 Adob​​e Flash Player。但是,这样的实现是允许的,并且确实更快。

memcpy您可能会发现 Windows 有不同的内存处理策略,而不是更慢。例如,第一次分配内存时,通常不会在所有内存中出错。您可能会发现 Linux(在某些情况下会预先设置后续页面)可能会因为该优化或其他优化而在这里表现得更好。如果 Windows 选择不这样做,可能是因为它使代码复杂化,或者因为它在通常在 Windows 上运行的实际用例中表现不佳。在综合基准测试中表现良好的可能与现实世界中表现良好的相匹配,也可能不匹配。

归根结底,这是一个实施质量问题。该标准要求它指定的功能以指定的方式运行,并且没有指定性能特征。memcpy如果该功能的性能对他们来说非常重要,一些项目会选择包含优化的实现。其他人选择不这样做,而是更愿意建议用户选择最能满足他们需求的平台,考虑到某些平台可能比其他平台表现更好。

于 2021-03-14T02:36:04.183 回答