Recently, I was intrigued by the Julia-lang as it claims to be a dynamic language that has near C performance. However, my experience with it so far is not good (at least performance wise).
The application that I'm writing requires random-access to specific array indices and then comparing their values with other specific array indices (over many iterations). The following code simulates my needs from the program:
My Julia code finishes executing in around 8seconds while the java-script code requires less than 1second on chrome environment!
Am I doing something wrong with the Julia code? Thanks a lot in advance.
Julia code here:
n=5000;
x=rand(n)
y=rand(n)
mn=ones(n)*1000;
tic();
for i in 1:n;
for j in 1:n;
c=abs(x[j]-y[i]);
if(c<mn[i])
mn[i]=c;
end
end
end
toc();
Javascript code: (>8 times faster than the julia code above!)
n=5000; x=[]; y=[]; mn=[];
for(var i=0; i<n; i++){x.push(Math.random(1))}
for(var i=0; i<n; i++){y.push(Math.random(1))}
for(var i=0; i<n; i++){mn.push(1000)}
console.time('test');
for(var i=0; i<n; i++){
for(var j=0; j<n; j++){
c=Math.abs(x[j]-y[i]);
if(c<mn[i]){
mn[i]=c;
}
}
}
console.timeEnd('test');
Performance Tips
Avoid global variables
A global variable might have its value, and therefore its type, change
at any point. This makes it difficult for the compiler to optimize
code using global variables. Variables should be local, or passed as
arguments to functions, whenever possible.
Any code that is performance critical or being benchmarked should be
inside a function.
We find that global names are frequently constants, and declaring them
as such greatly improves performance:
julia> const n = 5000; const x, y = rand(n), rand(n); const mn = fill(1000.0, n);
julia> function foo!(mn, x, y)
n = length(mn)
@inbounds for i in 1:n, j in 1:n
c = abs(x[j] - y[i])
if(c < mn[i])
mn[i] = c
end
end
return mn
end
foo! (generic function with 1 method)
julia> using BenchmarkTools: @btime
julia> @btime foo!(mn, x, y)
15.432 ms (0 allocations: 0 bytes)
Julia code should always be inside a function, so that the compiler can optimize it. Also, you are measuring both the compile time and the execution time: to get an accurate measure, you should call the function twice (the first for compilation).
function test(n)
x=rand(n);
y=rand(n);
mn=ones(n)*1000;
for i in 1:n;
for j in 1:n;
c=abs(x[j]-y[i])
if(c<mn[i])
mn[i]=c
end
end
end
(mn, x, y)
end
test(1)
@time test(5000);
This is taking 0.04s on my laptop. javascript in chromium 1s
(javascript in firefox web console 53s)