Hello there.
I have created a couple of functions with the same purpose, evaluating:
f(x, y) = (x - 3)^2 + (y + 15)^2
over a matrix (really two vectors), the first column for x and the second one for y. The first function I made is this one:
function fitness(P::Array{Float64})
v = Vector{Float64}(undef, size(P, 1))
for ii in eachindex(v)
v[ii] = f(P[ii, 1], P[ii, 2])
end
return v
end
after a while I realized the evaluation could be reduced to:
f.(a[:, 1], a[:, 2])
and both work perfectly.
However, I do not completely understand the results of benchmarking, as the more complex function seems to take way less time. Why does this happen?
Is it because preallocation? or the inherent allocations of broadcasting?
Code to benchmark:
using BenchmarkTools
a = rand(Float64, (1000, 2))
b = @benchmark fitness(a)
c = @benchmark f.(a[:, 1], a[:, 2])
I think the main overhead you are seeing is from the copies you perform when you write a[:,1].
Also you are benchmarking in global scope which might skew things a bit. Try:
using BenchmarkTools
a = rand(Float64, (1000, 2))
b = @benchmark $fitness($a)
c = @benchmark @views $f.($a[:, 1], $a[:, 2])
Apart from that: A broadcast is not very different from writing a straight-forward loop. In Julia loops are fast and you don’t to “vectorize” for performance like in Python.
$ generally means interpolation in Julia. You can e.g. interpolate strings:
But it is also commonly used in the context of macros when one want to insert expressions into other expressions. In this case it means that BenchmarkTools.jl inserts the value of the interpolated expression directly, i.e. it is not part of the benchmarking. Without interpolation in this case you include two things you don’t want: 1) lookup of the global variable a 2) a dynamic dispatch where Julia figures out which method it needs to call.
f is a regular function, and therefore a const. It does not require interpolation. If f were a non-const variable holding an function, however, it should be interpolated.
If f = sin, interpolate, if f(x) = sin(x), no need to interpolate.