更新:11.6.2016
我在 SICStus Prolog 4.3.2 中观察到的令人费解的性能差异在最近发布的 SICStus Prolog 4.3.3中完全消失了。赞!
我更新了下面的“运行时”表以包括 SICStus Prolog 4.3.3。亮点包括:
(is)/2
比以前快 10 倍。val_of/2
速度也非常快,几乎快了 2 倍!
美高;-)
在回答“ Prolog 语言中的大小程序”问题时, SO 用户 @ThanosTintinidis提出了一种非常简单的方法1,将初学者介绍给deriving length/2
:
[...] 另请注意,
E
仅需要实例化它是因为 is 将评估表达式。你可以这样写:大小([],0)。 大小([_|Xs],1+E):- 大小(Xs,E)。如果你称之为:
?- 大小([_,_],E)。 E = 1+(1+0)。有趣,不是吗?您可能想要评估最后一个
E
,即 call?- size([1,2], E), N is E
。[...]
乐趣? 大乐趣! 许多有趣的实验摆在面前:
左倾树与右倾树
list_siz L ([], 0)。%左倾_ list_sizL([_|Es], N+1) :- list_sizL(Es,N)。 list_siz R ([], 0)。%右倾_ list_sizR([_|Es], 1+N) :- list_sizR(Es,N)。
内置
(is)/2
vsval_of/2
val_of(V, E) :- ( E = E1+E2 -> val_of(V1, E1), val_of(V2, E2), V 是 V1+V2 ; 数字(E)-> V = E )。
go(2000000)
为了测量我使用不同的 Prolog 处理器2运行的运行时间:
去(左):- 长度(Xs,L), 成员(B_2,[list_sizL,list_sizR]), 呼叫(B_2,Xs,E), 成员(P_2,[是,val_of]), call_time (call(P_2,N,E), T), ( L = N -> writeq(B_2+P_2=T), nl ; throw(up) )。
在Intel Core i7-4700MQ 上,我使用 SICStus 和 SWI 观察到以下运行时:
| SWI | SICStus | SICStus | | 7.3.20 | 4.3.2 | 4.3 .3 | -------------------+--------+---------+---------| list_sizL + (is) | 208 毫秒 | 650 毫秒 | 60 毫秒| 3.4 倍 list_sizL + val_of | 381 毫秒 | 100 毫秒 | 60 毫秒 | 6.3 倍 -------------------+--------+---------+---------| list_sizR + (is) | 88 毫秒 | 660 毫秒 | 70 毫秒| 1.2x list_sizR + val_of | 346 毫秒 | 100 毫秒 | 60 毫秒 | 5.7 倍 -------------------+--------+---------+---------|
我对这些(可重现的)结果感到困惑......有人可以告诉我发生了什么吗?
脚注 1:为了简洁和可读性,变量名称稍作修改。
脚注 2:使用合适的命令行参数运行 SWI-Prolog 7.3.20 swipl -G2G -L2G -O
。