我想使用 SICStus Prolog 查看谓词目标内的执行时间。
示例:
pred :-
goal1,
time,
goal2,
time.
go :-
call(pred).
time_go :-
go,
times(go).
预期结果:
?- time_go.
times_go = 1000ms ,
times_go_goal1 = 500ms,
times_go_goal2 = 500ms
如何做到这一点?
我尝试了
time_out(:Goal, +Time, -Result)
中的 library(timeout)
,但收到此错误:
| ?- time_out(char_code(a,N), T, Res).
! Instantiation error in argument 2 of user:time_out/3
! goal: time_out(user:char_code(a,_193),_179,_181)
| ?- time_out(char_code(a,N), 1000, Res).
N = 97,
Res = success ? ; % Res=timeout in other example
您可以使用
statistics/2
来实现:
statistics(runtime,[Start|_]),
do_something,
statistics(runtime,[Stop|_]),
Runtime is Stop - Start.
或者,如果您想包含垃圾回收时间,则可以使用
total_runtime
代替 runtime
。 Start
和 Stop
以毫秒为单位进行测量,但上次我将其与 SICStus 一起使用时,它仅返回 10 的倍数。在一个项目中,我们使用对自定义外部 C 库的调用来检索更精细的分辨率。
对
time_out/3
的备注:它用于限制目标的运行时间,而不是测量其运行时间。如果目标及时完成,结果是 success
,如果需要更多时间,则中止执行(内部抛出超时异常),结果是 timeout
。
我想补充两个想法:
Prolog 允许回溯,因此目标可能多次成功。
您感兴趣的“运行时”是什么?
statistics/2
,但不要直接这样做。
相反,使用像这样的抽象
call_time/2
。示例查询:
?- call_time((排列([a,b,c,d,e,f,g,h,i],Xs),Xs=[_,_,g,f,e,d, c,b,a]), T_ms)。 Xs = [h, i, g, f, e, d, c, b, a], T_ms = 304 ; Xs = [i、h、g、f、e、d、c、b、a],T_ms = 345 ; 错误的。
请注意,
call_time/2
成功了两次,并且T_ms
测量了到目前为止的总运行时间。
由于没有人提到它,如果您只想显示时间,则 time/1 谓词也很有用。它已经被几个 Prolog 系统支持,例如 SWI-Prolog、Jekejeke Prolog、O-Prolog 等...:
Welcome to SWI-Prolog (threaded, 64 bits, version 7.7.19)
?- time((between(1,10000000,_), fail; true)).
% 10,000,001 inferences, 0.453 CPU in 0.468 seconds (97% CPU, 22068968 Lips)
true.
不幸的是,GNU Prolog、SICStus Prolog 等 Prolog 系统不支持它。但它类似于 Unix time 命令,因为它是一个带有目标参数的元谓词。比石器时代的方法更好。