10.2. benchmark.sci

This example shows a benchmark function that tries hard to do better than others. In the first step the timer resolution is determined. Next the function under test is executed in a loop and the time taken is estimated. This time in turn is used for the final test. The number of loop iterations is chosen according to the preliminary test. Finally, the median of the timings is returned.


function res = calibrate(max_len, n_avg, log_inc)
// determine the resolution of Scilab's built-in timer
// Return vector with measured timer resolution(s)

[nl, nr] = argn()
if nr <= 2, log_inc = 1.1, end
if nr <= 1, n_avg = 31, end
if nr == 0, max_len = 100000, end

r = []
n = 1
while n <= max_len
    //disp(n)
    tv = []
    iter = 0:n
    for k = 1:n_avg
        timer()
        for i = iter, end
        t = timer()
        tv = [tv; t]
    end
    tv = sort(tv)
    r = [r; [n, tv($/2 + 1)]]
    n = log_inc * n
end

// xbasc(); plot2d(r(:,1), r(:,2), -1)

delta = [r(:, 2); r($, 2)] - [r(1, 2); r(:, 2)]
idx = find(delta > %eps)
res = delta(idx)

function tpl = benchmark()
// return the time for one loop round trip

verbose = %t
min_test = 10  // minimum multiple of the timer
               // resolution to run coarse test
std_test = 200 // as min_test but for real test
n_avg = 31     // number of samples to calculate median
log_inc = 2.0  // logarithmic increment in coarse test

// inquire timer properties
disp('+++ calibrating timer')
resol = calibrate()
if size(resol, '*') <= 2 then
    error('calibration failed')
end
if resol(1) ~= resol(2) then
    warning('calibration botched; proceeding anyway...')
end
t_resol = resol(1);
if verbose
    disp('timer resolution is ' + string(t_resol) + 's')
end

// rough estimate of time
disp('+++ calibrating test')
np = 1
timer()
my_expensive_test()
t = timer()
while t < min_test * t_resol
    //disp(np, t, min_test * t_resol)
    np = log_inc * np
    timer()
    for i = 1:np
        my_expensive_test()
    end
    t = timer()
end
if verbose then 
    disp('coarse, ' + string(np) + ' round trips in ' 
         + string(t) + 's')
end
if np == 1 then
    warning('slow procedure under test -- time may be excessive')
end

// run real test
disp('+++ running test')
tc = t / np
ne = ceil(std_test * t_resol / tc)
if verbose then
    disp('fine, test will take about ' 
         + string(ceil(tc * ne * n_avg)) + 's')
end

r = []
for k = 1:n_avg
    timer()
    for i = 1:ne
        my_expensive_test()
    end
    t = timer()
    r = [r; t]
end
if verbose then
    disp('fine, ' + string(ne) + ' round trips in ' 
         + string(t) + 's')
end

// get median and return
r = sort(r)
//disp(r)
tpl = r($/2 + 1) / ne

function my_expensive_test()
exact = -2.5432596188;
z = abs( exact - intg(0, 2 * %pi, f) )

function y = my_cheap_test(x)
y = x