Dot vs. array comprehension vs. loop

First, you are breaking the very first rule in the performance tips: you are using a global variable xvec, rather than passing it as a parameter.

Second, you inner functions _f1(x) etcetera are referring to the variable ans, and Julia thinks that this is referring to the variable ans in the surrounding scope, which is not what you want (and is leading to unwanted allocations).

A better comparison would be:

function fdot(xvec)
    _f1(x) = 1/(1+x^2)
    return sum(@. xvec * _f1(xvec))
end
function fcompre(xvec)
    _f2(x) = 1/(1+x^2)
    return sum(x * _f2(x) for x in xvec)
end
function floop(xvec)
    _f3(x) = 1/(1+x^2)
    ans = 0.0
    for x in xvec
        ans += x * _f3(x)
    end
    return ans
end

from which I get:

julia> @btime fdot($xvec); @btime fcompre($xvec); @btime floop($xvec);
  3.776 μs (1 allocation: 7.94 KiB)
  3.488 μs (0 allocations: 0 bytes)
  3.402 μs (0 allocations: 0 bytes)

Note that fdot is slower because it allocates a temporary vector (to store @. xvec * _f1(xvec)) before calling sum.

I try to learn the way to speed up sums / integrals.

Note also that if you are computing integrals, you can generally do much better by using a quadrature scheme based on unequally-spaced points, e.g. via the QuadGK.jl package.

12 Likes