I need help understanding how/if I can speed up a function that has a ::Function
argument and a ::Vararg
argument.
I have several functions that do almost the same thing. They each receive a few vector arguments, calculate some new vectors of the same size, then do some nested while
looping to set the values of an output array. The looping part is almost identical across the different functions. The only difference is the function used to set the value of the output array inside the loops. So, I’m hoping to write a single function that takes care of this looping part once, then reuse it.
But because that inner loop function could take different numbers of arguments, I need to use a ::Vararg
input. I’ve tried and failed to get one that is as fast as having several nearly identical functions. An example is below.
test(x, y) = (x^2 + y^2)^(1/3)
test(x, y, z) = (x^2 + y^2 + z^2)^(1/4)
function funvar!(a::Vector, f::Function, V::Vararg{Vector{Float64},N}) where {N}
T = Tuple(zip(V...))
for i = 1:length(a)
a[i] = f(T[i]...)
end
end
function fun2!(a::Vector, f::Function, b::Vector, c::Vector)
for i = 1:length(a)
a[i] = f(b[i], c[i])
end
end
function fun3!(a::Vector, f::Function, b::Vector, c::Vector, d::Vector)
for i = 1:length(a)
a[i] = f(b[i], c[i], d[i])
end
end
N = 10000000
a = zeros(N)
b = rand(N)
c = rand(N)
d = rand(N)
@time funvar!(a, test, b, c)
@time funvar!(a, test, b, c, d)
@time fun2!(a, test, b, c)
@time fun3!(a, test, b, c, d)
3.095956 seconds (50.03 M allocations: 1.343 GiB, 6.75% gc time)
3.217017 seconds (60.04 M allocations: 1.641 GiB, 5.49% gc time)
0.953007 seconds (16.32 k allocations: 902.345 KiB)
0.899082 seconds (16.80 k allocations: 923.987 KiB)