Optimization Logtalk方法调用性能优化

Optimization Logtalk方法调用性能优化,optimization,prolog,logtalk,Optimization,Prolog,Logtalk,在使用Logtalk时,似乎我的程序使用Logtalk对象执行的时间比普通Prolog更长。我做了一个基准测试,比较了普通Prolog中简单谓词的执行情况与下面等价的logtalk对象封装: %% % plain prolog predicate plain_prolog_simple :- fail. %% % object encapsulation :- object(logtalk_obj). :- public([simple/0]). simple :-

在使用Logtalk时,似乎我的程序使用Logtalk对象执行的时间比普通Prolog更长。我做了一个基准测试,比较了普通Prolog中简单谓词的执行情况与下面等价的logtalk对象封装:

%%
% plain prolog predicate
plain_prolog_simple :-
  fail.

%%
% object encapsulation
:- object(logtalk_obj).

    :- public([simple/0]).
    simple :-
      fail.

:- end_object. 
以下是我得到的:

?- benchmark(plain_prolog_simple).

Number of repetitions: 500000
Total time calls: 0.33799099922180176 seconds
Average time per call: 6.759819984436035e-7 seconds
Number of calls per second: 1479329.3346604244
true.

?- benchmark(logtalk_obj::simple).

Number of repetitions: 500000
Total time calls: 2.950408935546875 seconds
Average time per call: 5.90081787109375e-6 seconds
Number of calls per second: 169468.0333888435
true.
我们可以看到
logtalk\u obj::simple call
plain\u prolog\u simple
调用慢。 我使用SWI Prolog作为后端,尝试设置一些日志对话标志,但没有成功

编辑:我们可以找到基准代码示例以


怎么了?为什么会出现这种性能差异?如何优化Logtalk方法调用?

简而言之,您正在对
::/2
目标的Logtalk编译进行基准测试,测试的是顶级解释器。这是一个典型的基准测试错误。顶层的目标(即纯Prolog目标、模块显式限定谓词目标或消息发送目标)总是要进行解释,即动态编译

对于编译的源文件中的消息发送目标,您可以获得接近普通Prolog的性能,这是最常见的场景。有关避免上述陷阱的基准测试解决方案,请参阅Logtalk发行版中的
基准测试
示例

性能差距(普通Prolog和Logtalk目标之间)取决于所选的后端Prolog编译器。当可以进行静态绑定时,对于成熟的Prolog vm(例如SICStus Prolog或ECLiPSe),这个差距可以忽略不计。然而,一些Prolog虚拟机(例如SWI-Prolog)缺乏一些可以使差距更大的优化,特别是在紧循环中

另外,Logtalk附带了一个用于开发的设置配置,而不是用于性能。请特别参阅
optimize
标志上的文档,静态绑定优化时应打开该标志

更新

从存储库中的代码开始,假设SWI Prolog是后端编译器,请尝试:

----- code.lgt -----
% plain prolog predicate
plain_prolog_simple :-
  fail.

% object encapsulation
:- object(logtalk_obj).

    :- public(simple/0).
    simple :-
      fail.

:- end_object.
--------------------

----- bench.lgt -----
% load the SWI-Prolog "statistics" library
:- use_module(library(statistics)).   

:- object(bench).

    :- public(bench/0).
    bench :-
        write('Plain Prolog goal:'), nl,
        prolog_statistics:time({plain_prolog_simple}).
    bench :-
        write('Logtalk goal:'), nl,
        prolog_statistics:time(logtalk_obj::simple).
    bench.

:- end_object.
---------------------
保存两个文件,然后启动Logtalk:

$ swilgt
...
?- set_logtalk_flag(optimize, on).
true.

?- {code, bench}.
% [ /Users/pmoura/Desktop/bench/code.lgt loaded ]
% (0 warnings)
% [ /Users/pmoura/Desktop/bench/bench.lgt loaded ]
% (0 warnings)
true.

?- bench::bench.
Plain Prolog goal:
% 2 inferences, 0.000 CPU in 0.000 seconds (69% CPU, 125000 Lips)
Logtalk goal:
% 2 inferences, 0.000 CPU in 0.000 seconds (70% CPU, 285714 Lips)
true.

time/1
谓词是元谓词。Logtalk编译器使用元谓词属性编译
time/1
参数。
{}/1
控件构造是一个Logtalk编译器旁路。它确保它的参数在普通Prolog数据库中被调用。

一个基准测试技巧,与SWI Prolog和YAP(可能是其他)一起工作,提供
时间/1
元谓词,就是将此谓词与Logtalk的
一起使用。您还可以制作速度相当快的面向对象的解释器。Jekejeke Prolog有一个纯解释(:)/2运算符。目前没有太多的开销。这是测试代码:

Jekejeke Prolog 3, Runtime Library 1.3.0
(c) 1985-2018, XLOG Technologies GmbH, Switzerland

?- [user].

plain :- fail.

:- begin_module(obj).

simple(_) :- fail.

:- end_module.
这是一些实际的结果。普通调用和基于(:)/2运算符的调用之间没有太大的区别。在引擎盖下,两个谓词查找都是内联缓存的:

?- time((between(1,500000,_), plain, fail; true)).
% Up 76 ms, GC 0 ms, Thread Cpu 78 ms (Current 06/23/18 23:02:41)
Yes

?- time((between(1,500000,_), obj::simple, fail; true)).
% Up 142 ms, GC 11 ms, Thread Cpu 125 ms (Current 06/23/18 23:02:44)
Yes
我们仍然有一笔开销,将来可能会被删除。必须做到的是,我们仍然要为每个(:)/2调用进行一次微型重写。但也许这会消失,我们正在努力


编辑2018年6月23日:我们现在在/3之间内置了一个,并且已经实施了一些优化。上面的数字显示了这个新原型的预览,它还没有推出。

真的谢谢。您说过“为了在编译的源文件中实现消息发送目标,要使性能接近普通的Prolog”,但是如何从swilgt编译(
logtalk\u load/2-3
compile on the fly only)?
logtalk\u load/1-2
编译和加载源文件(对于
logtalk\u load/1
,您可以在顶层使用
{}/1
快捷方式,如上例所示)。顶层的任何调用都会被解释,但这只会影响调用谓词的性能,而不会影响被调用谓词的功能。@j4nbur53请参阅@j4nbur53在使用动态绑定时,在Logtalk的情况下,我不需要这样的套件,因为级别数只在运行时对第一个
::/1
调用有影响。对于后续调用,将缓存查找。有关详细信息,请参见我上面评论中的链接。
?- time((between(1,500000,_), plain, fail; true)).
% Up 76 ms, GC 0 ms, Thread Cpu 78 ms (Current 06/23/18 23:02:41)
Yes

?- time((between(1,500000,_), obj::simple, fail; true)).
% Up 142 ms, GC 11 ms, Thread Cpu 125 ms (Current 06/23/18 23:02:44)
Yes