【问题标题】:Why the first time C program runs, it runs 10x slower为什么 C 程序第一次运行时,它的运行速度要慢 10 倍
【发布时间】:2012-11-13 17:46:31
【问题描述】:

我使用排序的 C 程序第一次运行速度比其他时间慢 10 倍。它使用整数文件进行排序,即使我更改数字,程序仍然运行得更快。当我重新启动 PC 时,第一次程序运行速度慢了 10 倍。我用time计算时间。

【问题讨论】:

  • 这是在 linux 上吗?如果是这样,它可能正在将程序信息存储在非活动内存中,从而使下次启动更有效率。也就是说,如果内存不是动态分配的
  • 可以肯定的是,创建 2 个文件,然后依次运行程序。
  • 有机会看到一些代码吗?
  • 你在运行time <cmd>吗?如果是这样,哪个组件的运行时间是原来的 10 倍?或者,您使用的是time_t time(time_t*); api?如果是这样,您是否尝试过使用 gprof 或您最喜欢的 XCode/Windows 分析器进行分析以查看哪些函数需要更长时间?
  • @RutgersMike 我使用时间

标签: c


【解决方案1】:

即使不再需要数据,操作系统也会将数据保存在 RAM 中(这称为“缓存”),因此当程序再次运行时,它会从那里获取所有数据并且没有磁盘 I/O。即使您更改了数据,该更改首先发生在 RAM 中,并且即使在写入文件后仍会保留在那里。

但请注意,它不会永远留在 RAM 中。如果其他东西需要内存,则删除缓存。此时,需要访问磁盘(此时它再次缓存在 RAM 中。)

这就是为什么重启后首次访问总是很慢的原因;由于从未从文件中读取数据,因此尚未缓存数据。

【讨论】:

  • 但是输入文件是随机生成的,数据个数一样,时间还是差不多,为什么会这样?此外,当我在文件中生成不同数量的数据时,我第一次运行它的时间比其他时间长。
  • @hey 当您更改数据大小时,对该数据的第一次运行不会比后续运行长 10 倍,对吧?
  • 是的,确实需要大约 10 倍的时间。
  • 我猜输入文件的名字是一样的吧?后续运行速度更快,因为操作系统可能已将文件缓存在内存中,并且您正在有效地处理 RAM 中的文件。我的猜测也是,如果您在后续运行之间等待一段时间(浏览、玩游戏等),运行时间大致相同,而不是少 10 倍。
  • @bye 每次运行程序之前都会生成输入文件吗?也是电脑开机后第一次之前?还是您正在启动计算机并读取计算机启动时已经存在的文件?
【解决方案2】:

你必须做出假设并将它们面对现实。您可以合理地做出的第一件事是,它确实闻起来很像缓存问题!

问自己这些问题:

  • 我的数据是否适合空闲 RAM(= 我的文件是否被 OS FS 缓存缓存 ?)
  • 我的数据是否适合 CPU 数据缓存?
  • 我的数据是否适合 HDD 内部缓存?

    1. 最容易丢弃的假设是 FS 缓存。在 linux 下,只需在每次调用程序之间发出 sync; echo 3 > /proc/sys/vm/drop_caches 即可。第一个将确保缓存的数据将进入物理介质(硬盘驱动器),第二个将从内存中删除文件系统缓存的内容。

    2. “物理介质”可能是 HDD 缓存本身,所以要小心... sdahdparm -W 0 /dev/sda 将完成这项工作。您可能希望在完成测试后重新启用它:)

    3. 另一个假设是CPU缓存,看看How can I do a CPU cache flush in x86 Windows?How to clear CPU L1 and L2 cache

好吧,它可能是也可能不是其中之一,但尝试一下也无妨:)

【讨论】:

    【解决方案3】:

    如果您的程序进行网络访问,那么这可能是初始延迟的原因。许多网络协议需要时间来设置。一些例子:

    • DNS:如果您的程序进行任何网络访问,它可能需要将主机名解析为 IP 地址。第一次它至少需要一次网络往返来填充本地缓存。以下请求会更短。
    • 网络文件系统(NFS、CIFS 等):可以通过网络打开文件。
    • 即使是一些看似无害的库函数也可能需要网络访问:主机的用户列表可以位于远程目录服务器上。

    除此之外,您可以使用一些低级跟踪工具来查看时间花在哪里。在 linux 上,一个基本工具是strace -r。其他系统可能有一些类似的工具。您的编译器还必须附带一个分析器(即 gprof 用于 GCC 或可能是 Valgrind)。

    【讨论】:

      【解决方案4】:

      我有一个非常相似的问题,但我没有加载一个大文件 - 所以我在第一次执行时间很长时感到困惑(缓存不可能是问题)。

      answer 为我指明了正确的方向 - 这是我的实时防病毒保护。每次我重新编译程序时,它都会重新扫描它,认为它可能是恶意的。我将我的项目路径作为“例外”添加到 Avira(就我而言)实时病毒防护。

      第一次执行时的程序执行速度现在变快了!

      【讨论】:

        【解决方案5】:

        这不是什么新鲜事,不仅仅是你的程序很多流行的商业软件都面临这个问题。

        首先检查这个MATLAB Article about slow fist time execution

        如果是在 C# 或 Java 等虚拟机上运行的其他编程语言,这很常见。 http://en.wikipedia.org/wiki/Just-in-time_compilation#Startup_delay_and_optimizations

        缓存是在 C 中发生这种情况的一个很好的理由,但 10 倍仍然是相当长的持续时间。也可能是您的系统在重新启动后正在加载其他资源。

        您应该在重新启动 10 分钟后运行程序以获得更好的结果。届时将加载所有启动应用程序。 (10分钟----取决于启动应用程序的数量和启动每个应用程序所需的时间)

        【讨论】:

          【解决方案6】:

          这是因为编译器优化,它的作用是缓存Temoparal Locality的结果并保存激活记录,也节省时间,因为在链接阶段不必再次重新加载绑定对象

          【讨论】:

            【解决方案7】:

            时间测量有两个组成部分

            如果您正在从磁盘读取文件,并将其加载到内存中并进行排序:

            1) 是时候读取文件并将其存储在数组中了 2)排序时间

            这些是分开测量的吗?

            你能检查一下吗? Invalidating Linux Buffer Cache

            如果不重新启动,如果重复清除缓存的实验得到相同的结果,那么您可以推断文件缓冲区缓存效果没有被考虑在内。

            【讨论】:

              猜你喜欢
              • 2011-11-19
              • 1970-01-01
              • 2014-10-09
              • 2014-08-18
              • 1970-01-01
              • 2020-10-03
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多