BProlog 8.1中不均匀的制表性能

时间:2015-05-04 08:54:39

标签: performance prolog memoization b-prolog prolog-tabling

我做了一些关于表格功能的实验 版本8.1并且对我观察到的表现感到非常惊讶。

这是我使用的代码。它计算将某些正整数N减少到I所需的Collatz1的数量:

%:- table posInt_CollatzSteps/2.               % remove comment to enable tabling
posInt_CollatzSteps(I,N) :-
   (  I == 1
   -> N = 0                                                % base case
   ;  1 is I /\ 1 
   -> I0 is I*3+1, posInt_CollatzSteps(I0,N0), N is N0+1   % odd
   ;  I0 is I>>1,  posInt_CollatzSteps(I0,N0), N is N0+1   % even
   ).

确定从I0I的所有整数所需的最大缩减步数:

i0_i_maxSteps0_maxSteps(I0,I,M0,M) :-
   (  I0 > I
   -> M0 = M
   ;  posInt_CollatzSteps(I0,N0),
      I1 is I0+1,
      M1 is max(M0,N0),
      i0_i_maxSteps0_maxSteps(I1,I,M1,M)
   ).

当我在没有表格的情况下运行一些查询?- time(i0_i_maxSteps0_maxSteps(1,1000000,0,MaxSteps)).时,我观察了以下运行时(以秒为单位):

  • 没有表格:6.784
  • 表格:2.323, 19.78 3.089 3.084 3.081

通过添加:- table posInt_CollatzSteps/2.,查询速度提高了2倍。我仍然感到困惑:

  • 第二轮比第一轮慢5倍以上。 显然大多数时间花在GC上。从第3次开始,表格变体再次快速。
  • 暖跑(第3,第4,......)明显慢于比冷(第1)跑。

我没想到这个!将此与我在版本3.6.0中观察到的运行时间进行对比:

  • w / o tabling:14.287
  • 表格:1.829, 0.31 0.308 0.31 0.333

我该怎么办?是否有任何指令或标志可以帮助我获得更好的BProlog性能?我在Linux上使用BProlog版本8.1 64位版本。

1 个答案:

答案 0 :(得分:0)

正在检查Jekejeke Prolog的表格。但只能去 到n = 100� 000。对于B-Prolog,以下命令行运行正常 在Windows上:

bp -s 40000000

据说这相当于160MB的堆栈/堆空间。我得到了两个 tabled和non-tabled比冷运行更好的暖运行:

  

B-Prolog n = 100' s:s   没有表格:14.276,12.229
  表格:0.419,0.143,0.127,0.152

Jekejeke的制表代码使用了运算符(< =)/ 2 模块。您需要手动将其添加到您的代码中:

  

Jekejeke Prolog / Minlog n = 100&000; 000 in s:
  没有表格:20.271,18.920
  表格:3.352,2.879,2.300,2.719

因此,Jekejeke仍有提升速度的空间。 关于你的B-Prolog问题:当记忆也是如此 紧张,这可能会无可替代地施加额外的压力 GC,可能会导致您观察到的行为。

再见

P.S。:这是Jekejeke Prolog的标签代码。你需要 安装Jekejeke Minlog以使模块 hypo 可用。最好 是安装最新版本:

/* with memoization */
:- thread_local posInt_CollatzStepsm/2.

mposInt_CollatzSteps(I,N) :-
   (  I == 1
   -> N = 0                                                % base case
   ;  posInt_CollatzStepsm(I,N)
   -> true
   ;  1 is I /\ 1
   -> I0 is I*3+1, mposInt_CollatzSteps(I0,N0), N is N0+1,   % odd
      <= posInt_CollatzStepsm(I,N)
   ;  I0 is I>>1,  mposInt_CollatzSteps(I0,N0), N is N0+1,   % even
      <= posInt_CollatzStepsm(I,N)
   ).