You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:48:04