1

我想对谓词 int_cntA/2 进行微基准测试...

int_cntA(I,W) :- I >= 0, int_cntA0_cntA(I,0,W).

int_cntA0_cntA(0,W0,W) :- !, W0 = W.
int_cntA0_cntA(I,W0,W) :- I0 is I/\(I-1), W1 is W0+1,      int_cntA0_cntA(I0,W1,W).

...针对谓词 int_cntB/2:

int_cntB(I,W) :- I >= 0, int_cntB0_cntB(I,0,W).

int_cntB0_cntB(0,W0,W) :- !, W0 = W.
int_cntB0_cntB(I,W0,W) :- I0 is I>>1,     W1 is W0+(I/\1), int_cntB0_cntB(I0,W1,W).

我不是 100% 确定我需要考虑什么才能获得好的结果……什么是有趣的维度?

到目前为止,我想出了:我应该将元调用性能包括在基准测试中还是应该与原始数字运算有关?循环是否应该由故障驱动?我应该关心执行期间产生的垃圾吗?

以下代码片段是一个简单的基准测试实现,它适用于原始性能,是故障驱动的,并且(因此)不关心垃圾:

:- use_module(library(between)).

rep_10.
rep_10.
rep_10.
rep_10.
rep_10.
rep_10.
rep_10.
rep_10.
rep_10.
rep_10.

rep_100M :- rep_10, rep_10, rep_10, rep_10, rep_10, rep_10, rep_10, rep_10.

int_cntA/2 的代码:

benchA_1(I,W,Rt) :- statistics(runtime,_),
                    ( repeat(100000000),      int_cntA(I,W), false ; true ),
                    statistics(runtime,[_,Rt]),
                    int_cntA(I,W).

benchA_2(I,W,Rt) :- statistics(runtime,_),
                    ( between(1,100000000,_), int_cntA(I,W), false ; true ),
                    statistics(runtime,[_,Rt]),
                    int_cntA(I,W).

benchA_3(I,W,Rt) :- statistics(runtime,_),
                    ( rep_100M,               int_cntA(I,W), false ; true ),
                    statistics(runtime,[_,Rt]),
                    int_cntA(I,W).

int_cntB/2 的代码:

benchB_1(I,W,Rt) :- statistics(runtime,_),
                    ( repeat(100000000),      int_cntB(I,W), false ; true ),
                    statistics(runtime,[_,Rt]),
                    int_cntB(I,W).

benchB_2(I,W,Rt) :- statistics(runtime,_),
                    ( between(1,100000000,_), int_cntB(I,W), false ; true ),
                    statistics(runtime,[_,Rt]),
                    int_cntB(I,W).

benchB_3(I,W,Rt) :- statistics(runtime,_),
                    ( rep_100M,               int_cntB(I,W), false ; true ),
                    statistics(runtime,[_,Rt]),
                    int_cntB(I,W).

在运行 SICStus Prolog 4.3.1 的 Intel Core i7 Haswell 机器上,由于不同的基准测试方法(A、B、C)导致的最坏情况性能差异超过 100%:

| ?- benchA_1(0,W,Rt).
W = 0,
Rt = 3140 ? 
yes
| ?- benchA_2(0,W,Rt).
W = 0,
Rt = 4130 ? 
yes
| ?- benchA_3(0,W,Rt).
W = 0,
Rt = 1960 ? 
yes

如果/如何进一步降低微基准测试的开销,您有什么想法吗?谢谢!

4

1 回答 1

1

你必须小心冷热运行。现代 Prolog 系统具有及时索引甚至编译。这样不同的运行就可以表现不同。垃圾收集也使时间变化。

我总是测量热运行,所以我至少先运行一次基准测试,然后放弃测量。然后我再次运行它并记下测量值。

转换不同的循环。通常的方法是通过在循环中插入一个虚拟谓词并测量循环时间来测量循环开销。然后再减去这个时间。虚拟谓词可以很容易地定义为:

  dummy.

如果您看到循环头很小,我认为不考虑减去循环开销的长度并明确说明您的测量值也测量循环也是有效的。

当您使用相同的循环时,您仍然可以比较您的线束运行的不同测试对象的结果,即使您不减去。

于 2015-04-25T11:41:26.500 回答