The Octave benchmark timings look rather extreme on your benchmark table (julialang.org). I have looked at the benchmark code and it simply does not represent how one would actually program in that language. You write that the micro benchmarks shall “give a sense how … numerical programming in that particular language is … all of the benchmarks are written to test the performance of specific algorithms, expressed in a reasonable idiom in each language”. The micro benchmark for Octave absolutely fails that pretended target.
Let me show you how I would reasonably implement the algorithms in Octave (probably also works in proprietary Matlab, but I can't check that). I haven't spend more than a minute to think about each algorithm.
Could you please clarify what the actual purpose of your benchmarks is? I would be fine with the benchmarks saying: Loops and recursion in Octave are slow. However, the benchmark table suggests that, e.g., computing the Mandelbrot set in Octave is much slower than it actually is.
diff --git a/test/perf/micro/perf.m b/test/perf/micro/perf.m
index 6c6a846..2a1fadb 100644
--- a/test/perf/micro/perf.m
+++ b/test/perf/micro/perf.m
@@ -32,9 +32,9 @@ function perf()
assert(issorted(sortperf(5000)))
timeit('quicksort', @sortperf, 5000)
- s = pisum(true);
+ s = pisumvec(true);
assert(abs(s-1.644834071848065) < 1e-12);
- timeit('pi_sum',@pisum, true)
+ timeit('pi_sum',@pisumvec, true)
%s = pisumvec(true);
%assert(abs(s-1.644834071848065) < 1e-12);
@@ -80,25 +80,29 @@ function timeit(name, func, varargin)
end
%% recursive fib %%
+%% (the function definition is recursive, but the algorithm uses a loop) %%
-function f = fib(n)
- if n < 2
- f = n;
+function f = fib (n)
+ if n <= 0
+ f = 0;
return
- else
- f = fib(n-1) + fib(n-2);
end
+
+ f = ones (1, n);
+ for k = 3 : n
+ f(k) = f(k-2) + f(k-1);
+ end
+ f = f(n);
end
%% parse int %%
+%% create t random uint32 numbers, convert them all to hex and parse them %%
-function n = parseintperf(t)
- for i = 1:t
- n = randi([0,2^32-1],1,'uint32');
- s = dec2hex(n);
- m = hex2dec(s);
- assert(m == n);
- end
+function n = parseintperf (t)
+ n = randi ([intmin('uint32'), intmax('uint32')], t, 1, 'uint32');
+ s = dec2hex (n);
+ m = hex2dec (s);
+ assert (m == n);
end
%% matmul and transpose %%
@@ -109,60 +113,44 @@ end
%% mandelbrot set: complex arithmetic and comprehensions %%
-function n = mandel(z)
- n = 0;
+function n = mandel (z)
+ n = zeros (size (z));
c = z;
- for n=0:79
- if abs(z)>2
- return
+ for k = 1 : 80
+ idx = abs (z) <= 2;
+ if any (any (idx))
+ n(idx) ++;
+ z(idx) = z(idx) .^ 2 + c(idx);
+ else
+ break
end
- z = z^2+c;
end
- n = 80;
end
function M = mandelperf(ignore)
- M = zeros(length(-2.0:.1:0.5), length(-1:.1:1));
- count = 1;
- for r = -2:0.1:0.5
- for i = -1:.1:1
- M(count) = mandel(complex(r,i));
- count = count + 1;
- end
- end
+ [r, i] = meshgrid (-2 : .1 : 0.5, -1 : .1 : 1);
+ M = mandel (complex (r, i));
end
%% numeric vector quicksort %%
-function b = qsort(a)
- b = qsort_kernel(a, 1, length(a));
-end
-
-function a = qsort_kernel(a, lo, hi)
- i = lo;
- j = hi;
- while i < hi
- pivot = a(floor((lo+hi)/2));
- while i <= j
- while a(i) < pivot, i = i + 1; end
- while a(j) > pivot, j = j - 1; end
- if i <= j
- t = a(i);
- a(i) = a(j);
- a(j) = t;
- i = i + 1;
- j = j - 1;
- end
- end
- if lo < j; a=qsort_kernel(a, lo, j); end
- lo = i;
- j = hi;
+function b = qsort (a)
+ if length (a) <= 1
+ b = a;
+ return
end
+
+ pivot = a(1);
+ lo = a <= pivot;
+ hi = a >= pivot;
+ % keep pivot out of lo and hi
+ lo(1) = hi(1) = false;
+ b = vertcat (qsort (a(lo)), pivot, qsort (a(hi)));
end
-function v = sortperf(n)
- v = rand(n,1);
- v = qsort(v);
+function v = sortperf (n)
+ v = rand (n, 1);
+ v = qsort (v);
end
%% slow pi series %%
@@ -180,7 +168,7 @@ end
%% slow pi series, vectorized %%
function s = pisumvec(ignore)
- a = [1:10000]
+ a = [1:10000];
for j=1:500
s = sum( 1./(a.^2));
end
@@ -224,10 +212,8 @@ end
%% printf %%
-function printfd(n)
- f = fopen('/dev/null','w');
- for i = 1:n
- fprintf(f, '%d %d\n', i, i);
- end
- fclose(f);
+function printfd (n)
+ f = fopen ('/dev/null', 'w');
+ fprintf (f, '%d %d\n', 1:n, (1:n)+1);
+ fclose (f);
end
Let me risk another approach on #2412 and #5128.
The Octave benchmark timings look rather extreme on your benchmark table (julialang.org). I have looked at the benchmark code and it simply does not represent how one would actually program in that language. You write that the micro benchmarks shall “give a sense how … numerical programming in that particular language is … all of the benchmarks are written to test the performance of specific algorithms, expressed in a reasonable idiom in each language”. The micro benchmark for Octave absolutely fails that pretended target.
Let me show you how I would reasonably implement the algorithms in Octave (probably also works in proprietary Matlab, but I can't check that). I haven't spend more than a minute to think about each algorithm.
Could you please clarify what the actual purpose of your benchmarks is? I would be fine with the benchmarks saying: Loops and recursion in Octave are slow. However, the benchmark table suggests that, e.g., computing the Mandelbrot set in Octave is much slower than it actually is.