【问题标题】:Understanding RAM speed using malloc, memtest and dd使用 malloc、memtest 和 dd 了解 RAM 速度
【发布时间】:2018-10-05 12:17:46
【问题描述】:

在使用新硬件时,我编写了一段 C 代码来测试 RAM 速度和磁盘速度。本质上它是 3 行在 RAM 中写入 5 GB 并将其写入文件,我围绕该文件设置了一些计时器:

long long int AMOUNT = 5*1024*1024*1024l;
FILE *file_handle = fopen('test.bin', 'wb');
handle = malloc(AMOUNT);
memset(handle, 0, AMOUNT);
fwrite(handle, AMOUNT, 1, file_handle);

然后我用 dd 使用 ramdisk 或 tempfs 进行了尝试:

mount -t tmpfs /mnt/temp1 /mnt/temp1
dd if=/dev/zero of=/mnt/temp1/test bs=1M

然后,回到磁盘:

dd if=/mnt/temp1/test of=/home/user/test bs=1M

在下表中,我的结果,我也插入了speed memtest 7.5。我不明白 9.0 以及 memtest 和其他数字之间的巨大区别......谁能解释一下?

【问题讨论】:

  • 您可以归咎于软件和操作系统开销。我在我的机器上尝试了 dd 并得到了 4.4 GB/s,这比 CPU 的能力慢很多倍(多线程 memcpy)。
  • @Lundin 我看不出提问者在哪里不“谦虚”,或者他们在哪里“责备”。
  • @nullp0tr 对不起,在我上面的评论中是针对安蒂的。
  • 我仍然想知道为什么 malloc 在具有 2133Mt/s 内存的 6600U 上如此之快
  • 排除了编译器的差异...排除了 INT 而不是 LONG LONG INT...只是不明白

标签: c memory ram dd


【解决方案1】:

有很多因素在起作用,我无法迭代其中的大部分,也无法理解它们。但这里有一些在后台发生的事情的简要介绍:

虚拟内存

在大多数现代用户系统上,您实际上并没有直接访问 RAM。您有多个间接层,其中之一是虚拟内存。 VM 是您的进程访问的内存,就好像它是普通的连续 RAM,但实际上底层系统将其转换为 RAM 中的正确地址。因此,使用虚拟地址访问物理内存几乎肯定不会为您提供您正在寻找的数据。

虚拟内存也有层。现代处理器包括对虚拟内存的本机支持,它通常由MMU 控制,与处理器接近或位于同一芯片上。

许多操作系统也有自己的虚拟内存层,然后它们要么转换为处理器上的 MMU 管理的虚拟内存,要么直接转换为物理 RAM。

只是一个兔子洞有多远的例子,Linux 实际上有惰性内存分配。因此,当您第一次分配内存时,它不会与 CPU 通信,而只是保存在内核数据结构中,当您稍后访问内存时,CPU 会生成一个Page Fault。然后内核的页面错误处理程序查看该内存是否被延迟分配,如果是,则实际分配它。

内核空间与用户空间

用户空间程序不允许直接修改物理内存,对于 *nixes 他们调用System Calls 来为他们做这件事。系统调用会改变 CPU 的运行模式,通常是一个相对缓慢的操作。

库函数

像malloc 这样的库函数实际上必须做大量的簿记工作,以确保当您在指针上调用free 时,您只会释放该部分。但他们也批量分配。 *nixes 上的malloc 调用系统调用mmap 来分配页面。后续的malloc 调用将继续使用该页面,直到您需要更多。

这与这个问题有什么关系?

以上只是您使用内存时发生的事情的一瞥,因此您如何分配内存,传递给系统的数量和标志会改变很多事情,并且可以解释结果之间的差异。

建议

尝试在这些进程上运行strace,看看它们大部分时间都花在了哪里!

【讨论】:

    【解决方案2】:

    你的整个实验都失败了,因为你还没有意识到表达式和类型提升在 C 中是如何工作的。

    5*1024*1024*1024l 是 4 个操作数,每个操作数的类型为 int。您将结果存储在哪种类型与如何执行计算无关。它们在int 上执行,因为每个* 的操作数都是int 类型。

    在主流 32/64 位 2 的编译器上。系统,int 的值最高可达 2^31 -1 = 21.4 亿。所以这个表达式溢出,你调用了一个未定义的行为错误。从那时起在你的程序中发生的事情没有意义。

    将所有整数常量更改为具有ULL 后缀,然后重新开始。

    【讨论】:

    • 最后一个有'l'后缀,让溢出错误消失了,所以我觉得还不错。
    • @Niels 啊,这就是我们写L 而不是l 的原因,后者在某些字体(如Courier)中看起来像数字1(一)。反正*是从左到右关联的,所以1024L之前的先验计算是在int类型上进行的,最后计算524万*1024是在long上计算的。这通常也是 4 个字节,而不是 8 个字节。所以bug还在,后缀没有修复。
    • 使用malloc的速度差异在使用1024*1024*1024时保持不变,在max_value(int)之内
    猜你喜欢
    • 1970-01-01
    • 2012-01-17
    • 2014-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多