用于运行K次基准测试代码的Unix命令

00jrzges  于 2022-11-04  发布在  Unix
关注(0)|答案(8)|浏览(142)

假设我有一个在Unix中执行的代码,如下所示:

$ ./mycode

我的问题是,有没有一种方法可以计算代码执行K次的时间,比如K = 1000。
我知道Unix的“time”命令,但那只执行了1个示例。

imzjd6km

imzjd6km1#

改进/澄清Charlie的答案:

time (for i in $(seq 10000); do ./mycode; done)
pgx2nnw8

pgx2nnw82#

尝试

$ time ( your commands )

在括号中写一个循环,以便根据需要重复命令。

更新

好的,我们可以解决命令行太长的问题。这是bash语法,如果你使用的是其他shell,你可能需要使用 expr(1)

$ time (
> while ((n++ < 100)); do echo "n = $n"; done
> )

real    0m0.001s
user    0m0.000s
sys     0m0.000s
2ledvvac

2ledvvac3#

给你个建议确保这个“基准测试”接近于你对执行程序的真实的使用。如果这是一个短暂的进程,那么仅仅创建进程就可能会产生很大的开销。不要认为这和在你的程序中将它作为一个循环实现是一样的。

35g0bw71

35g0bw714#

为了稍微增强一些其他的响应,如果您决定测试,其中一些响应(基于seq的响应)可能会导致命令行太长,比方说测试一百万次。

time ( a=0 ; while test $a -lt 10000 ; do echo $a ; a=`expr $a + 1` ; done)
n53p2ov0

n53p2ov05#

另一个解决“命令行太长”问题的方法是在bash中使用C风格的for循环:

$ for ((i=0;i<10;i++)); do echo $i; done

这在zsh中也是有效的(虽然我打赌zsh有更好的使用方法,但我对zsh还是个新手)。

drkbr07n

drkbr07n6#

忘记time,hyperfine将做正是你正在寻找:https://github.com/sharkdp/hyperfine

% hyperfine 'sleep 0.3'
Benchmark 1: sleep 0.3
  Time (mean ± σ):     310.2 ms ±   3.4 ms    [User: 1.7 ms, System: 2.5 ms]
  Range (min … max):   305.6 ms … 315.2 ms    10 runs
lvmkulzt

lvmkulzt7#

Linux perf stat有一个-r repeat_count选项,它的输出只给出每个硬件/软件事件的平均值和标准差,而不是最小值/最大值。
它并没有放弃第一次运行作为热身或任何东西,但它在很多情况下有点有用。
滚动到右侧查看stddev结果,如( +- 0.13% )的周期数。该结果中的差异比task-clock中的差异小,可能是因为CPU频率 * 不是 * 固定的。(我特意选择了一个非常短的运行时间,尽管使用Skylake硬件P状态和EPP=性能,即使与34毫秒的运行时间相比,它也应该能够非常快地加速到最大加速。但是对于一个完全不受内存限制的CPU任务,它的解释器循环每次迭代以恒定的时钟周期数运行,仅对分支预测失误和中断取模。--all-user仅对用户空间的CPU事件(如指令和周期)进行计数,而不对中断处理程序和系统调用/页面错误进行计数。)

$ perf stat --all-user -r5   awk 'BEGIN{for(i=0;i<1000000;i++){}}'

 Performance counter stats for 'awk BEGIN{for(i=0;i<1000000;i++){}}' (5 runs):

             34.10 msec task-clock                #    0.984 CPUs utilized            ( +-  0.40% )
                 0      context-switches          #    0.000 /sec                   
                 0      cpu-migrations            #    0.000 /sec                   
               178      page-faults               #    5.180 K/sec                    ( +-  0.42% )
       139,277,791      cycles                    #    4.053 GHz                      ( +-  0.13% )
       360,590,762      instructions              #    2.58  insn per cycle           ( +-  0.00% )
        97,439,689      branches                  #    2.835 G/sec                    ( +-  0.00% )
            16,416      branch-misses             #    0.02% of all branches          ( +-  8.14% )

          0.034664 +- 0.000143 seconds time elapsed  ( +-  0.41% )

这里的awk只是一个繁忙的循环,它为我们提供了一些可以测量的东西。如果您要使用它对循环或函数进行微基准测试,请将其构建为具有最小的启动开销(占总运行时间的一小部分),因此整个运行的perf stat事件计数主要反映了您想要计时的代码。通常,这意味着在您自己的程序中构建一个重复循环,对初始化的数据进行多次循环。
另请参见Idiomatic way of performance evaluation?-由于测量开销的原因,很难对非常短的事情进行计时。仔细构建一个重复循环,告诉你一些关于被测代码吞吐量或延迟的有趣信息,这一点很重要。
运行之间的变化是经常发生的,但是通常像这样的连续运行在组内的变化要比间隔半秒到up-arrow/return的运行之间的变化小。也许是因为透明的大页面可用性,或者对齐方式的选择?通常是针对小型微基准测试,所以对从页面缓存中逐出的文件不敏感。
(The X1 M7 N1 X打印的+-范围只是我认为基于小样本量的一个标准差,而不是它看到的全部范围。)

qfe3c7zg

qfe3c7zg8#

如果你担心不断地将可执行文件加载和卸载到进程空间的开销,我建议你设置一个ram磁盘,并从那里为你的应用计时。
早在70年代,我们曾经能够在可执行文件上设置一个“粘性”位,并将其保留在内存中。我不知道现在有哪个Unix支持这种行为,因为它使更新应用程序成为一场噩梦。

相关问题