Prolog 序言:测试是否设置了位

Prolog 序言:测试是否设置了位,prolog,benchmarking,microbenchmark,sicstus-prolog,Prolog,Benchmarking,Microbenchmark,Sicstus Prolog,我使用任意精度的整数来表示大小不等的密集位向量 从十几个到几千个 我的代码经常需要检查某些位是否已设置(或未设置), 因此,我做了一些微观基准测试,看看一些变化是否比其他变化快得多: bench_1(0, _, _) :- !. bench_1(N, V, P) :- V /\ (1 << P) =\= 0, N0 is N-1, bench_1(N0, V, P). bench_2(0, _, _) :- !. bench_2(N, V, P) :- (V >> P) /\ 1

我使用任意精度的整数来表示大小不等的密集位向量 从十几个到几千个

我的代码经常需要检查某些位是否已设置(或未设置), 因此,我做了一些微观基准测试,看看一些变化是否比其他变化快得多:

bench_1(0, _, _) :- !. bench_1(N, V, P) :- V /\ (1 << P) =\= 0, N0 is N-1, bench_1(N0, V, P). bench_2(0, _, _) :- !. bench_2(N, V, P) :- (V >> P) /\ 1 =:= 1, N0 is N-1, bench_2(N0, V, P). bench_3(0, _, _) :- !. bench_3(N, V, P) :- (V >> P) /\ 1 =\= 0, N0 is N-1, bench_3(N0, V, P). bench_4(0, _, _) :- !. bench_4(N, V, P) :- (V >> P) /\ 1 > 0, N0 is N-1, bench_4(N0, V, P). bench_5(0, _, _) :- !. bench_5(N, V, P) :- 1 is (V >> P) /\ 1, N0 is N-1, bench_5(N0, V, P). 我使用以下代码进行微基准测试:

call_indi_delta(G, What, Delta) :-
   statistics(What, [V0|_]),
   call(G),
   statistics(What, [V1|_]),
   Delta is V1 - V0.

run(Ind, Reps, Expr, Pos) :-
   Position is Pos,
   Value    is Expr,
   member(P_3, [bench_1,bench_2,bench_3,bench_4,bench_5,bench_6]),
   G =.. [P_3,Reps,Value,Position],
   call_indi_delta(G, Ind, T_ms), 
   write(P_3:Reps=T_ms), nl,
   false.

使用
run(runtime,10000000,1No,我不认为有比您尝试的公式更快的公式。特别是,在SICStus中没有比
getbit/2
更快的公式(在编译算术时甚至没有在内部使用)

注:一般来说,我会使用
walltime
进行基准测试。目前的操作系统并不能提供非常可靠的
运行时


PPS.我会添加一个使用测试代码序列的虚拟版本的基准测试,只是为了确保测试代码的实际成本比基准测试工具的成本要高得多。(我这样做了,并用一个不做任何事情的
dummy/3
调用替换位测试,使测试速度更快。因此,基准测试看起来还行。)

SWI Prolog from(朝下看)。你知道SICStus是如何实现多精度整数的吗?@Boris。我知道GMP,但我不知道SWI是如何集成它的。(我仍然迷失在SWI源代码中。)谢谢你的链接!关于SICStus:我不知道,但我有一种预感,它会导致一些实质性的调用开销,但我不确定…我会尝试使用C接口来检查。SWI对太大的整数使用GMP。如果你在src/*.C中grep获取getbit,你可以找到我链接的代码行。@Boris。我知道了。但是它是如何实现的呢andle memory allocation?GMP允许注册自定义分配器,但有一个重要的警告:“GMP可能会使用已分配的块来保存指向其他已分配块的指针。这将限制保守的垃圾收集方案可以做出的假设。”Thx!我应该尝试使用IIRC吗?调用开销在SICStus 4.3.2(64位)的JIT中出现了一点偏高,这种情况发生了变化吗?我也尝试了
walltime
。我希望看到有大位向量的明显GC开销(IIRC GC时间是
walltime
的一部分)。我很惊讶我没有这么做。@重复我的猜测是fli的开销太高(而且从C访问大整数的内容也不是免费的),但不尝试就很难知道。
call_indi_delta(G, What, Delta) :-
   statistics(What, [V0|_]),
   call(G),
   statistics(What, [V1|_]),
   Delta is V1 - V0.

run(Ind, Reps, Expr, Pos) :-
   Position is Pos,
   Value    is Expr,
   member(P_3, [bench_1,bench_2,bench_3,bench_4,bench_5,bench_6]),
   G =.. [P_3,Reps,Value,Position],
   call_indi_delta(G, Ind, T_ms), 
   write(P_3:Reps=T_ms), nl,
   false.
| SWI | SWI -O | SICStus | SICStus | | 7.3.23 | 7.3.23 | 4.3.2 | 4.3.3 | --------+-----------------+-------------------| bench_1 | 4547ms | 3704ms | 900ms | 780ms | bench_2 | 4562ms | 3619ms | 970ms | 850ms | bench_3 | 4541ms | 3603ms | 970ms | 870ms | bench_4 | 4541ms | 3633ms | 940ms | 890ms | bench_5 | 4502ms | 3632ms | 950ms | 840ms | --------+-----------------+-------------------| bench_6 | 1424ms | 797ms | n.a. | n.a. |