Linux Time命令微秒或更高精度

12

我希望知道在Linux下,程序执行所需的时间,单位为微秒(或更高的精度)。目前我使用的是time命令,但它只能提供最大毫秒级别的准确度。是否有一些方法可以调整time命令以获得更高的准确度,或者有其他命令可以实现相同的功能?

5个回答

8
你的问题没有意义:即使在毫秒级时间内也不会获得重复的测量值。
添加更多数字只会增加噪音。您可以从/dev/random中获取额外的数字。

1
我不明白你的观点。我说我想要比毫秒更精确的准确性,在今天的处理器上这并不是不可能的,我们甚至可以获得纳秒级别的准确性。增加更多数字如何增加更多噪音? - Pushpak Dagade
7
由于在非实时操作系统上运行的代码没有确定性执行,所以需要指导。只需要操作系统处理一些IP数据包,或者运行另一个任意进程,或者crond唤醒以检查是否应该执行某些操作,或者文件系统决定它应该写出脏页等等,你正在计时的进程就会被暂停一段(很短的)时间,从而导致计时不准确。操作系统内置的定时功能,如CPU时间(相对于墙钟时间),通常也是按照一定分辨率(通常为1个内核滴答、1毫秒或更长时间)计数的。 - nos
4
使用time /bin/sleep 0.006进行快速测试,似乎表明噪声小于1毫秒。因此,尽管此类测量肯定存在风险,但Guanidene的请求本身并非毫无意义。 - Joachim Breitner
1
@JoachimBreitner,您正在测量一个没有任何作用的命令。对于任何实际执行操作的命令,在调度程序内部的变异性可能会使最终测量值超过+/-1ms。即使使用/bin/sleep,您也只能获得亚毫秒级别的准确度,而不是Guanidene所要求的微秒级别准确度。 - Employed Russian
@EmployedRussian 为什么调度程序会区分 sleep 和其他命令?对于测量噪音来说,sleep 同样有效。 - ssmid

4
使用gettimeofday -- 提供微秒级精度。

4

我同意Employed Russian's answer。对于这样的测量,希望微秒级别的准确度并没有太多意义。因此,你所获得的任何附加数字都是无意义的(实际上是随机的)。

如果你有要测量的应用程序的源代码,可以使用clockclock_gettime函数,但不要指望超过几十微秒的准确度。还有RDTSC机器指令。

请阅读linux clock howto

不要忘记,从应用程序的角度来看,执行时间是不确定和不可重现的(考虑到上下文切换、缓存未命中、中断等在随机时间发生)。

如果你想要衡量整个程序的性能,请至少运行几秒钟,并测量时间多次(例如8次),然后取平均值(也许去掉最好和最差的计时)。
如果你想要测量特定函数的时间,请学习如何对你的应用进行分析(如gprofoprofile等等...)。还可以参考这个问题
不要忘记阅读time(7)
请注意,在当前(笔记本电脑、台式机、服务器)具有复杂CPU缓存和TLB以及分支预测器的乱序执行 流水线 超标量处理器上,一些微小循环或机器指令序列的执行时间是不可重现的(纳秒计数将从一次运行到下一次变化)。操作系统还会添加随机性(调度, 上下文切换, 中断, 页面缓存, 写时复制, 需求分页...),因此没有意义测量超过1毫秒 -或者如果你很幸运的话,可能是100微秒- 精度的某个命令的执行。您应该多次对您的命令进行基准测试。
为了得到显著的结果,您应该将基准应用程序更改为运行超过几秒钟(例如在main中添加一些循环或使用更大的数据集...),并重复执行基准命令十几次。然后取这些度量值的平均值(或最差值、最好值,具体取决于您想要的内容)。
如果系统time(1)不足够,您可以制作自己的测量设备;还可以参见getrusage(2);但我对您能够获得更准确的结果持怀疑态度。

顺便提一下,我的i3770K最近在GNU/Linux(4.2内核,Debian/Sid/x86-64)桌面电脑上,“系统”调用比如time(2)clock_gettime(2)执行时间约为3到4纳秒(多亏了vdso(7)避免了真正的syscall负担...),所以你可以经常在程序内部使用它们。


clock() 在我的机器上相当无用。 clock() 随时间的不准确性(以秒为单位):time_t t0 = time(NULL); clock_t c0 = clock(); while (1) { printf("\r%ld", (clock() - c0) / CLOCKS_PER_SEC - (time(NULL) - t0)); } - ssmid
在我的电脑上,15分钟后它是-180。 - ssmid

1

看看 current_kernel_time() 对你的需求是否有帮助。 我使用过它,并发现它非常有用,因为它提供了纳秒级的精确度。 更多详细信息请点击这里


0

Linux perf CLI 工具

像其他人提到的那样,微秒级别的时间在现代系统中只是噪音。

在 Linux 中实现微秒级(或更高)进程计时 询问是否有任何方法可以减少内核产生的变异性。

perf CLI 工具可以打印微秒及更多信息,这将使我们能够看到这些测量值只是噪音的程度。

Ubuntu 22.04 设置:

sudo apt install linux-tools-common linux-tools-generic
echo -1 | sudo tee /proc/sys/kernel/perf_event_paranoid

循环CYCLES个周期的x86汇编程序:

main.S

.text
.global _start
_start:
    mov $0, %rax
    mov $CYCLES, %rcx
.Lloop_label:
    inc %rax
    loop .Lloop_label

    /* exit */
    mov $60, %rax   /* syscall number */
    mov $0, %rdi    /* exit status */
    syscall

组装并运行:

cpp -DCYCLES=100000 main.S main.cpp.S
as -o main.o main.cpp.S
ld -o main.out main.o
perf stat ./main.out

在我的Lenovo ThinkPad P51上进行的一些样本结果:

CYCLES 经过的时间(秒)
10^9 1.3秒
10^8 0.13秒
10^7 0.014秒
10^6 1.9毫秒
10^5 0.6 - 0.8毫秒
10^4 0.4 - 0.8毫秒

从这里我们可以看到,毫秒级别的数字在某种程度上是有意义的,并且随着规模的增大而有所缩放:循环次数减少10倍意味着时间减少10倍。

但是,在大约0.1毫秒左右,事情完全停止了缩放,我们必须测量完全随机的其他东西,而不是程序执行。

你也可以尝试创建裸机程序:如何在没有操作系统的情况下运行程序? 我想知道在这种情况下BIOS和硬件本身会产生多少噪音,这将是一个有趣的尝试。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接