SWI-Prolog中能否获取谓词执行的微秒级耗时?
在SWI-Prolog中实现微秒级谓词执行计时
当然可以实现微秒级计时!SWI-Prolog提供了比statistics(walltime, ...)精度更高的工具,而且你提到的“多次执行取平均”也是一个非常实用的优化方案,我来详细拆解这两种思路:
方法一:使用get_time/1直接获取微秒级精度
SWI-Prolog的get_time/1谓词会返回一个以秒为单位的浮点数,其精度通常能达到微秒级(具体取决于操作系统的时钟精度,现代系统一般都支持1微秒甚至更高)。我们可以用它来改写你的计时谓词:
chronometrise_us(X) :- write('Executing: '), write(X), nl, nl, get_time(Start), call(X), get_time(End), TimeUs is (End - Start) * 1_000_000, nl, write('Time: '), write(TimeUs), write(' μs.'), nl.
工作原理
get_time(Start)记录目标执行前的时间戳- 调用目标
X后,get_time(End)记录结束时间戳 - 计算时间差并乘以1e6,将秒转换为微秒
这个方法能直接给出单次执行的微秒级耗时,适合本身执行时间就有一定长度的谓词。
方法二:多次执行取平均(适合短耗时谓词)
你提到的“执行1000次取平均”的思路非常聪明——对于执行时间极短的谓词,单次微秒计时可能会因为系统调度、时钟粒度等因素产生较大误差,多次执行后取平均能得到更可靠的结果。这里给你扩展一个支持重复执行的版本:
chronometrise_repeat(X, N) :- write('Executing '), write(N), write(' times: '), write(X), nl, nl, get_time(Start), repeat_n(X, N), get_time(End), TotalUs is (End - Start) * 1_000_000, AvgUs is TotalUs / N, nl, write('Total time: '), write(TotalUs), write(' μs.'), nl, write('Average time per run: '), write(AvgUs), write(' μs.'), nl. repeat_n(_, 0) :- !. repeat_n(X, N) :- call(X), N1 is N - 1, repeat_n(X, N1).
使用示例
比如测试一个简单的递归谓词:
factorial(0, 1). factorial(N, F) :- N > 0, N1 is N - 1, factorial(N1, F1), F is N * F1.
调用chronometrise_repeat(factorial(1000, _), 1000).就能得到1000次执行的总耗时和平均微秒耗时。
补充说明
statistics(walltime, [_, E])返回的是毫秒级的耗时,这是因为它的设计定位是提供粗粒度的计时,而get_time/1则是为了高精度时间测量而生。- 如果你需要区分CPU时间和壁钟时间,SWI-Prolog还提供了
statistics(cputime, Time),它返回的是CPU耗时(秒为单位的浮点数),同样可以转换为微秒级。
内容的提问来源于stack exchange,提问作者2manov
相关产品推荐
相关产品推荐

