我想获取某个进程执行所需的微秒数。有人知道如何在 Linux 系统上执行此操作吗?(我正在寻找比毫秒更精确的时间值,因为我正在测量一些非常敏感的东西。)
注意:我认为时间命令无法达到我想要的精度……它似乎只能精确到毫秒,这对于我的目的来说还不够好
答案1
你应该看看巴基斯坦石油工业协会。 顺便提一句,那里'类似的问题。
答案2
你没有说明这是否是你自己的代码,以及你是否想在内部对其中的某些部分进行计时。你也没有说明你实际上想要完成什么。
您可能正在执行的一件事是在 shell 中运行某个程序。如果是这样,最直接的方法是对进程的多次调用进行计时并进行计算。
重击:
t=($({ time -p for i in {1..1000000}; do some_prog; done; } 2>&1))
echo "scale=6;${t[1]}/1000000" | bc
如果您的date
命令(和系统)支持纳秒并且您不介意开销:
begin=$(date +%s.%N); some_prog; end=$(date +%s.%N); echo "scale=6; $end - $begin" | bc
答案3
Linux perf
CLI 工具
在现代系统中,微秒级的时间只不过是噪音而已。
https://stackoverflow.com/questions/182554/microsecond-accurate-or-better-process-timing-in-linux询问是否有任何方法可以减少内核产生的可变性。
CLI工具perf
确实会打印微秒及更多内容,这将使我们能够看到这些测量结果只是噪音。
Ubuntu 22.04 设置:
sudo apt install linux-tools-common linux-tools-generic
echo -1 | sudo tee /proc/sys/kernel/perf_event_paranoid
循环的 x86 汇编程序CYCLES
:
电源
.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
我的联想 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 毫秒的时候,事情完全停止了扩展,而且我们测量的不是程序执行,而是其他完全随机的东西。
您还可以尝试创建裸机程序:https://stackoverflow.com/questions/22054578/how-to-run-a-program-without-an-operating-system/32483545#32483545我想知道在这种情况下 BIOS 和硬件本身会产生多大的噪音,这将是一个有趣的尝试。
有关的:https://stackoverflow.com/questions/8586354/linux-time-command-microseconds-or-better-accuracy
答案4
times(2)
返回以 jiffies 为单位的进程时间,而不是时间。因此,它只能像内核频率一样精确地测量时间单位。clock_gettime(2)
如果内核编译正确,则可以实现更精确的分辨率,但没有易于使用的用户空间接口。