我有一个简单的C代码来完成这个任务(伪代码):
#define N 100000000
int *DataSrc = (int *) malloc(N);
int *DataDest = (int *) malloc(N);
memset(DataSrc, 0, N);
for (int i = 0 ; i < 4 ; i++) {
StartTimer();
memcpy(DataDest, DataSrc, N);
StopTimer();
}
printf("%d\n", DataDest[RandomInteger]);
我的个人电脑:IntelCorei7-3930,4x4GB DDR3 1600内存运行RedHat 6.1 64位.
第一个memcpy()
以1.9GB/秒的速度出现,而接下来的三个为6.2GB/s。缓冲区大小(N
)太大,不可能由缓存效应造成。所以,我的第一个问题是:
memcpy()
要慢得多呢?也许malloc()
在使用它之前不会完全分配内存?如果消除了memset()
,那么第一个memcpy()
以1.5GB/秒的速度运行,而接下来的三个memcpy()
以11.8GB/秒的速度运行。快2倍了。我的第二个问题是:
memcpy()
,为什么memset()
快2x?发布于 2014-05-18 15:32:35
正如其他人已经指出的,Linux使用乐观内存分配策略。
第一个和接下来的memcpy
之间的区别是DataDest
的初始化。
正如您已经看到的,当您消除memset(DataSrc, 0, N)
时,第一个memcpy
甚至更慢,因为源的页面也必须被分配。当您同时初始化DataSrc
和DataDest
时,例如。
memset(DataSrc, 0, N);
memset(DataDest, 0, N);
所有memcpy
都将以大致相同的速度运行。
对于第二个问题:当您使用memset
初始化分配的内存时,所有页面都将被连续排列。另一方面,当您复制时分配内存时,源页和目标页将被交错分配,这可能会造成差异。
发布于 2014-05-18 14:52:26
这很可能是由于VM子系统中的延迟分配造成的。通常,当您分配大量内存时,只有第一个N页实际被分配并连接到物理内存中。当您访问这些第一个N页之后,就会生成页面错误,并在“按需”的基础上分配和连接更多的页面。
至于问题的第二部分,我相信有些VM实现实际上跟踪零页并专门处理它们。尝试将DataSrc
初始化为实际(例如随机)值,并重复测试。
https://stackoverflow.com/questions/23723215
复制相似问题