为什么相同的memcpy-glibc实现在Linux上更快,在Windows上更慢?
我注意到,在相同硬件上,Linux上的为什么相同的memcpy-glibc实现在Linux上更快,在Windows上更慢?,linux,windows,glibc,questdb,Linux,Windows,Glibc,Questdb,我注意到,在相同硬件上,Linux上的memcpy比Windows更快。我用英特尔I7 4770 CPU和16GB RAM双启动同一个盒子,并运行相同的C++代码编译。我正在尝试使用此代码测试memccpy #include <iostream> #include <chrono> #include <cstring> typedef std::chrono::high_resolution_clock Clock; int main() { co
memcpy
比Windows更快。我用英特尔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;
}
}
#包括
#包括
#包括
typedef std::chrono::高分辨率时钟;
int main(){
常数int mb=300;
int size=mb*1024*1024/sizeof(int);
自动缓冲区=新整数[大小];
srand(1);
对于(int i=0;i std::coutmemcpy
是标准C库的一部分,因此,由运行代码的操作系统提供(如果使用不同的libc,则由另一个提供程序提供)。对于已知大小的小副本,GCC通常会内联这些操作,因为它通常可以避免函数调用的开销,但对于大的或未知的大小,它通常会使用系统函数
在这种情况下,您会看到glibc和Windows有不同的实现,glibc提供了一个更好的选择。glibc确实在不同的平台上提供了几种不同的变体,这些变体基于对给定CPU最有效的方式,但Windows可能不会这样做,或者可能有一个优化程度较低的实现
在过去,glibc甚至利用了memcpy
不能有重叠参数的事实,并在一些CPU上向后复制,但不幸的是,这破坏了一些不符合标准的程序,尤其是Adobe Flash Player。然而,这样的实现是允许的,而且确实更快
与memcpy
更慢不同的是,您可能会发现Windows有不同的内存处理策略。例如,在第一次分配内存时,通常不会在所有内存中出错。您可能会发现Linux在某些情况下会导致后续页面故障,但由于这种优化,Linux在这里的性能可能会更好如果Windows选择不这样做,可能是因为它使代码复杂化,或者是因为它在通常在Windows上运行的现实世界用例中表现不佳。在合成基准中表现良好的可能与现实世界中表现良好的不匹配
归根结底,这是一个实现质量问题。该标准要求它指定的函数以指定的方式运行,而不指定性能特征。一些项目选择包括优化的memcpy
实现,如果该函数的性能对它们来说非常重要。其他项目选择不这样做并建议用户选择最能满足其需求的平台,同时考虑到某些平台的性能可能比其他平台更好。memcpy
是标准C库的一部分,因此,由运行代码的操作系统提供(如果您使用不同的libc,则由其他提供商提供)。对于已知大小的小副本,GCC通常会内联这些操作,因为它通常可以避免函数调用的开销,但对于大的或未知的大小,它通常会使用系统函数
在这种情况下,您会看到glibc和Windows有不同的实现,glibc提供了一个更好的选择。glibc确实在不同的平台上提供了几种不同的变体,这些变体基于对给定CPU最有效的方式,但Windows可能不会这样做,或者可能有一个优化程度较低的实现
在过去,glibc甚至利用了memcpy
不能有重叠参数的事实,并在一些CPU上向后复制,但不幸的是,这破坏了一些不符合标准的程序,尤其是Adobe Flash Player。然而,这样的实现是允许的,而且确实更快
与memcpy
更慢不同的是,您可能会发现Windows有不同的内存处理策略。例如,在第一次分配内存时,通常不会在所有内存中出错。您可能会发现Linux在某些情况下会导致后续页面故障,但由于这种优化,Linux在这里的性能可能会更好如果Windows选择不这样做,可能是因为它使代码复杂化,或者是因为它在通常在Windows上运行的现实世界用例中表现不佳。在合成基准中表现良好的可能与现实世界中表现良好的不匹配
归根结底,这是一个实现质量问题。该标准要求它指定的函数以指定的方式运行,而不指定性能特征。一些项目选择包括优化的memcpy
实现,如果该函数的性能对它们来说非常重要。其他项目选择不这样做并建议用户选择最能满足其需求的平台,同时考虑到某些平台的性能可能比其他平台更好。这两个操作系统的memcpy()
实现方式不同,显然Linux(好吧,glibc)的优化效果更好。或者还有其他问题影响您的基准计时(实际CPU时间是比wall c更好的度量