【问题标题】:does building from a RAM drive truly yield speed increase?从 RAM 驱动器构建真的会提高速度吗?
【发布时间】:2016-09-12 18:36:37
【问题描述】:

我正在处理一个项目,该项目包含数千个 .cpp 文件以及数千个 .h.hpp,构建需要 28 分钟 从 SSD 运行。

几周前,我们从另一家公司继承了这个项目,但仔细阅读了 makefile,他们通过 .NOPARALLEL 假目标明确禁用了并行构建;我们正在尝试找出他们是否有充分的理由。

在最坏的情况下,加快速度的唯一方法是使用 RAM 驱动器。

所以我按照Tekrevue 的说明安装了Imdisk,然后使用CrystalDiskMark 运行基准测试:

固态硬盘 内存驱动器

我还使用 Cygwin 运行 dd,与我的 SSD 相比,RAM 驱动器的速度显着提高(至少 3 倍)。

但是,我的构建时间不会改变一分钟!

然后我想:也许我的专有编译器调用了一些 Windows API 并导致速度大大降低,所以我在 Cygwin 上从源代码构建了 fftw

我的预期是我的处理器使用率会增加到某个最大值并在构建期间保持在那里。相反,我的用法非常尖锐:每个编译的文件一个。我知道即使 Cygwin 仍然必须与 Windows 交互,所以我仍然使用尖峰 proc 的事实让我认为问题不是我的编译器。

好的。新理论:为每个源文件调用编译器在 Windows 中有一些巨大的开销,因此,我从我的构建日志中复制粘贴并将 45 个文件传递给我的编译器,并将其与分别调用编译器 45 次进行比较。调用 ONCE 速度更快,但 45 个文件总共只用了 4 秒。 而且我看到了与为每个文件调用一次编译器时相同的“尖峰”处理器使用情况。

为什么即使从 RAM 驱动器运行,编译器也不能更快地运行?开销是多少?

更新 #1 我认为,评论者一直在说,RAM 驱动器是一种不必要的 bc 窗口无论如何都会将输入和输出文件缓存在 RAM 中。 另外,RAM 驱动器的实现(即驱动程序)可能不是最理想的。 所以,我不再使用 RAM 驱动器了。

另外,人们说我应该多次运行 45 文件构建以消除缓存开销:我运行了 4 次,每次都是 52 秒

CPU 使用率(编译结束前 5 秒)

虚拟内存使用 当编译器将内容输出到磁盘时,它实际上首先缓存在 RAM 中,对吗? 那么这个屏幕截图表明 IO 不是问题,或者更确切地说,它和我的 RAM 一样快。

问题: 因此,既然一切都在 RAM 中,为什么 CPU % 没有更多的时间呢? 我可以做些什么来加快单线程/作业构建速度吗? (记住现在是单线程构建)

更新 2 下面建议我应该将我的 compile-45-files 调用的关联性设置为 1,这样 Windows 就不会在调用时反弹到多个内核。 结果:

100% 单核使用!相同的 52 秒

所以不是硬盘驱动器、RAM 或缓存​​,而是 CPU 才是瓶颈。

**谢谢大家! ** 为您提供帮助

================================================ ==========================

我的机器:Intel i7-4710MQ @ 2.5GHz,16GB RAM

【问题讨论】:

  • 编译 CPU 不绑定吗?
  • @BaummitAugen 如果为真,我的 CPU 将始终接近 100%,但事实并非如此。
  • 每次构建都需要重新制作所有内容吗?听起来有机会通过管理依赖关系来减少需要完成的工作量。
  • 如果禁用并行构建,CPU 将不会接近 100%。一个核心将是。如果您还没有使用预编译头文件,那么它们可以极大地提高构建速度。
  • 推测:.NOPARALLEL 的存在可能是因为Makefile 没有正确捕获所有依赖项,并且它们无法让并行构建正常工作。你试过删除.NOPARALLEL吗?

标签: c++ windows performance makefile


【解决方案1】:

您的跟踪显示 CPU 使用率为 23%。您的 CPU 有 4 个实际内核(使用超线程使其看起来像 8 个)。因此,您只使用了一个核心,达到了绝对最大值(正负 2%,这可能比您真正预期的准确度更高)。

由此得出的明显结论是,您的构建过程受 CPU 限制,因此提高磁盘速度不太可能产生太大影响。

如果您想要大幅加快构建速度,您需要找出当前 makefile 的问题所在,或者编写没有问题的全新 makefile,这样您就可以同时支持部分构建和并行构建。

这可以让你获得很多。基本上你所做的任何其他事情(加速磁盘、超频 CPU 等)最多只会带来很小的收益(如果你真的很幸运,可能会获得 20%,适当的构建环境可能至少会提供 20:1大多数典型构建的改进)。

【讨论】:

    【解决方案2】:

    从驱动器读取源代码是编译软件开销中非常非常小的一部分。您的 CPU 速度更为相关,因为解析和生成二进制文件是该过程中最慢的部分。

    **更新 您的图表显示 CPU 非常繁忙,我不确定您希望看到什么。除非构建是多线程的并且您的内核停止调度其他不那么密集的线程,否则这肯定是处理器繁忙的图表。

    【讨论】:

    • 我的 CPU 根本没有被征税。这在问题中非常清楚。
    • 链接步骤占用大量磁盘空间。
    • @EJP 除了我使用的是内存驱动器并且即使在编译期间 CPU 也很低。
    • @Adrian 我看到一个 CPU 经常出现峰值。你为什么要打折?您的 CPU 通常不会像您所说的那样 100% 挂钩,因为您正在执行单线程构建。绝对您的图表显示 CPU 可能是因素。
    • 您在 4 个内核(8 个“超线程”)上获得了 23% 的利用率。这相当于让一个核心或多或少地一直处于忙碌状态。我认为,如果您将所有 8 个图表叠加在一起,峰值会合并成看起来像 25% 的 CPU 使用率的东西。各个内核的峰值可能是由于编译器调用(不同的进程)被 make 启动了。操作系统在不同的内核上运行它们。虽然存在线程关联,但我所知道的不同进程之间没有核心关联(可能存在一些允许它的作业 API)。
    【解决方案3】:

    我不明白您为什么如此指责操作系统,除了顺序、愚蠢的 IO(加载源/保存中间输出 - 应该通过看到 SSD 和 ramdisk 执行相同的操作来排除)和进程启动(通过编译单个巨型文件排除)编译器和操作系统之间几乎没有交互。

    现在,一旦您排除了“磁盘”和处理器,我预计瓶颈将是内存速度 - 不是 RAM 磁盘 IO 部分(可能已经大部分被 SSD 饱和),而是编译过程自己。

    这实际上是一个相当普遍的问题,此时处理器通常比内存快,这通常是瓶颈(这就是目前编写缓存友好代码至关重要的原因)。处理器可能正在浪费大量时间等待从主内存中获取缓存数据。

    无论如何,这都是猜测。如果你想要一个可靠的答案,像往常一样,你必须进行分析。从a list like this 获取一些采样分析器,然后查看编译器在哪里浪费时间。就个人而言,我希望看到大量缓存未命中(如果您为 ramdisk 烧掉了太多 RAM,甚至会出现页面错误),但任何事情都可能发生。

    【讨论】:

    • 我倾向于这个答案,因为我已经消除了 RAM 或 CPU 速度的问题。使用分析器,我会看到什么表明它是缓存?
    • @Adrian:查找高速缓存未命中计数器上的高值、长时间将 CPU 标记为停止等待内存的情况以及内存绑定指令上的大量样本。跨度>
    • 好的,现在看一下图表,我们可以看到它实际上是受 CPU 限制的 - 左边的小图表显示平均 23% 的四个内核,这几乎是一个完整的内核一直在忙碌.在单个内核图表上更难看到,因为操作系统正在围绕内核移动线程。您可以尝试将make进程的进程亲和性设置为单个核心,子进程应该继承它。
    • 我尝试使用start "" /node 1 /affinity 0x1 build_one_qcc.bat,但得到the system cannot accept the start command parameter 1
    • 我发现了问题:/node 是在谈论套接字,而不是逻辑核心。
    猜你喜欢
    • 2013-06-10
    • 2018-01-19
    • 2020-12-05
    • 1970-01-01
    • 2021-07-26
    • 2016-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多