【发布时间】:2014-07-06 13:20:04
【问题描述】:
我有执行此操作的简单 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]);
我的电脑: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 倍?
【问题讨论】:
-
如果你从一个未初始化的源中 memcpy 不是 UB 吗?您使用什么编译器进行了哪些优化?通过将数据大小增加 10 倍或更多,使计时更可靠。
-
@usr 数据是随机的,没有ub,只要你不以可能引入ub的方式使用数据。示例中没有可以执行此操作的代码。
-
顺便说一句:11.8GB/s 的总线速度对我来说似乎有点太快了。
-
@usr 读取未初始化的变量不会触发 ub,错误地使用该值会触发。例如,使用该值访问数组偏移量将触发 ub。我猜技术上(标准)你是对的。
-
这可能是正确的,但 OP 特别提到了 gcc 和 linux。此外:int 没有可能的陷阱表示(并且从不使用 int,只复制)否则从未知磁盘文件中读取随机 dat 也可能导致问题。
标签: c performance memory-management