【问题标题】:Is the UNIX `time` command accurate enough for benchmarks? [closed]UNIX `time` 命令对于基准测试是否足够准确? [关闭]
【发布时间】:2012-02-18 20:47:27
【问题描述】:

假设我想对两个程序进行基准测试:foo.py 和 bar.py。

几千次运行以及time python foo.pytime python bar.py 各自的平均值是否足以分析和比较它们的速度?


编辑: 此外,如果每个程序的执行时间都在亚秒以下(假设不是上述情况),那么 time 仍然可以使用?

【问题讨论】:

  • 单次执行的运行时间是多久?如果小于一秒,很可能会因为精度差而产生系统误差,而且系统误差不会通过平均来消除。
  • 一般来说,我首先要分析的代码的执行时间要比一秒长得多。
  • 此外,即使密集代码的执行时间为亚秒级,在程序内部执行该操作一百万次左右是否会减轻系统错误?这样,time 将比较 foo 的一百万次运行与 bar 的一百万次运行。
  • 同意。但是例如从 makefile 或其他 shell 脚本调用十万次的亚秒级程序可能值得分析,但单独的时间将毫无意义。

标签: linux unix profiling benchmarking


【解决方案1】:

time 为运行超过一秒的基准测试产生了足够好的时间,否则 exec() 处理进程所花费的时间与其运行时间相比可能会很大。

但是,在进行基准测试时,您应该注意上下文切换。也就是说,另一个进程可能正在使用 CPU,从而与您的基准测试竞争 CPU 并增加其运行时间。为避免与其他进程发生争用,您应该运行如下基准测试:

sudo chrt -f 99 /usr/bin/time --verbose <benchmark>

或者

sudo chrt -f 99 perf stat -ddd <benchmark>

sudo chrt -f 99 在 FIFO 实时类中以优先级 99 运行您的基准测试,这使您的进程成为最高优先级进程并避免上下文切换(您可以更改您的 /etc/security/limits.conf 以便它不需要特权进程使用实时优先级)。

它还使time 报告所有可用的统计信息,包括您的基准测试发生的上下文切换次数,通常应该为 0,否则您可能希望重新运行基准测试。

perf stat -ddd/usr/bin/time 提供更多信息,并显示诸如每周期指令、分支和缓存未命中等信息。

最好禁用 CPU 频率缩放和提升,以便 CPU 频率在基准测试期间保持恒定以获得一致的结果。

【讨论】:

  • 这是最通透的答案,但是程序执行时间小于一秒的情况呢?
  • 谢谢克里斯。如果花费的时间不到一秒钟,那么大部分时间可能是exec()ing 这个过程。最好让基准测试运行几秒钟,以尽量减少启动时间偏差。
【解决方案2】:

现在,imo,没有理由使用time 进行基准测试。请改用perf stat。它为您提供了更多有用的信息,并且可以在任何给定的时间重复基准测试过程并对结果进行统计,即计算方差和平均值。这比time 更可靠且易于使用:

perf stat -r 10 -d <your app and arguments>

-r 10 将运行您的应用程序 10 次并对其进行统计。 -d 输出更多数据,例如缓存未命中。

因此,虽然time 对于长时间运行的应用程序可能足够可靠,但它肯定不如perf stat 可靠。改用它。

附录:如果你真的想继续使用time,至少不要使用bash-builtin命令,而是在详细模式下真正处理:

/usr/bin/time -v <some command with arguments>

然后输出例如:

    Command being timed: "ls"
    User time (seconds): 0.00
    System time (seconds): 0.00
    Percent of CPU this job got: 0%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.00
    Average shared text size (kbytes): 0
    Average unshared data size (kbytes): 0
    Average stack size (kbytes): 0
    Average total size (kbytes): 0
    Maximum resident set size (kbytes): 1968
    Average resident set size (kbytes): 0
    Major (requiring I/O) page faults: 0
    Minor (reclaiming a frame) page faults: 93
    Voluntary context switches: 1
    Involuntary context switches: 2
    Swaps: 0
    File system inputs: 8
    File system outputs: 0
    Socket messages sent: 0
    Socket messages received: 0
    Signals delivered: 0
    Page size (bytes): 4096
    Exit status: 0

特别注意这是如何测量峰值 RSS 的,如果您想比较补丁对峰值内存消耗的影响,这通常就足够了。 IE。使用该值比较之前/之后,如果 RSS 峰值显着下降,那么您做对了。

【讨论】:

  • 在 Debian 上你需要 linux-tools-$version 包。
  • 在 Ubuntu 上安装 linux-tools-generic(通过 this question
【解决方案3】:

是的,time 足够准确。并且您只需要运行您的程序十几次(如果运行持续时间超过一秒,或一秒的很大一部分——即至少超过 200 毫秒)。当然,对于大多数运行(第一次除外),文件系统会很热(即小文件已经缓存在 RAM 中),因此请考虑到这一点。

你想让time-d 运行至少十分之几秒的原因是时间测量的准确性和粒度。不要期望不到百分之一秒的准确度。 (你需要一些特殊的内核选项来让它有一毫秒)

在应用程序内部,您可以使用clockclock_gettimegettimeofdaygetrusagetimes(它们肯定有 Python 等价物)。

别忘了阅读 time(7) 手册页。

【讨论】:

  • time -d 是什么?我在 linux 或 OSX 的手册页中没有看到该参数。
  • 我指的是形容词timed,参考time命令
【解决方案4】:

是的。 time 命令给出了经过的时间以及消耗的 CPU。后者可能是您应该关注的,除非您正在执行大量 I/O。如果经过的时间很重要,请确保系统在运行测试时没有其他重要活动。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多