表现:memset

时间:2014-05-18 14:49:07

标签: c performance memory-management

我有简单的C代码(psuedo代码):

#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]);

我的电脑:Intel Core i7-3930,4x4GB DDR3 1600内存,运行RedHat 6.1 64位。

第一个memcpy()以1.9 GB /秒的速度发生,而接下来的三个以6.2 GB /秒的速度发生。 缓冲区大小(N)太大,不能由缓存效果引起。所以我的 第一个问题:为什么第一个memcpy()这么慢?也许malloc()在你使用它之前没有完全分配内存?

如果我删除了memset(),那么第一个memcpy()以大约1.5 GB /秒的速度运行, 但接下来的三个以11.8 GB /秒的速度运行。几乎是加速的2倍。我的第二个问题: 如果我不调用memset(),为什么memcpy()会快2倍?

2 个答案:

答案 0 :(得分:5)

这很可能是由于VM子系统中的延迟分配造成的。通常,当您分配大量内存时,只会实际分配前N个页面并将其连接到物理内存。当您访问前N页以外的页面时,会生成页面错误,并在“按需”按键上分配和连接其他页面。基础。

关于问题的第二部分,我相信一些VM实现实际上跟踪归零页面并专门处理它们。尝试将DataSrc初始化为实际值(例如随机值)并重复测试。

答案 1 :(得分:5)

正如其他人已经指出的那样,Linux使用optimistic memory allocation strategy

第一个和以下memcpy之间的差异是DataDest的初始化。

正如您已经看到的,当您消除memset(DataSrc, 0, N)时,第一个memcpy甚至更慢,因为必须同时分配源的页面。初始化DataSrc DataDest时,例如

memset(DataSrc, 0, N);
memset(DataDest, 0, N);

所有memcpy s的运行速度大致相同。

对于第二个问题:当您使用memset初始化已分配的内存时,所有页面将连续布局。另一方面,当您在复制时分配内存时,源页面和目标页面将被交错分配,这可能会有所不同。