Sato
Sato

Reputation: 1133

Optimizing Julia performance when an interpolated function has to be accessed multiple times as global variable

I am trying to apply the following performance tips in my code concerning the global variable issue: https://docs.julialang.org/en/v1/manual/performance-tips/

As far as I understood, to improve performance, one should avoid the use of global variables (especially when they have to be called in big loops) by declaring them as const, trying to use them as local variables, or annotating the type every time when it is used.

Now I have an interpolated function (obtained through interpolating an array in Interpolations.jl) named minus_func, the type of which obtained through typeof function:

getfield(Main, Symbol("#minus_func#877")){Interpolations.Extrapolation{Float64,3,ScaledInterpolation{Float64,3,Interpolations.BSplineInterpolation{Float64,3,OffsetArrays.OffsetArray{Float64,3,Array{Float64,3}},BSpline{Cubic{Line{OnCell}}},Tuple{Base.OneTo{Int64},Base.OneTo{Int64},Base.OneTo{Int64}}},BSpline{Cubic{Line{OnCell}}},Tuple{StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}},StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}},StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}}},BSpline{Cubic{Line{OnCell}}},Periodic{Nothing}},getfield(Main, Symbol("#get_periodic#875"))}

This minus_func is declared as a global variable, and will be called many times in a loop (and may be changed, so I don't prefer to declare it as a const). Is it possible to annotate its type when it's called such that the performance can be improved? If so, how? As in the following example, where x is annotated to the type Vector{Float64}:

global x = rand(1000)

function loop_over_global()
    s = 0.0
    for i in x::Vector{Float64}
        s += i
    end
    return s
end

So how do I improve the performance of the following code in the same way, given that minus_func is global?

function loop_over_global()
    s = 0.0
    for i in 1:1000
        s += minus_func(i, 1, 1)  # Let's say, the function takes three integer arguments
    end
    return s
end

Upvotes: 1

Views: 236

Answers (1)

Bill
Bill

Reputation: 6086

You could make the global into a function argument, so that that function argument is not global:

using BenchmarkTools

function fminus(i, j, k)
    return i - k - j
end

minus_func = fminus

function loop_over_global()
    s = 0.0
    for i in 1:1000
        s += minus_func(i, 1, 1)
    end
    return s
end

function loop_over_global_witharg(f::Function)
    s = 0.0
    for i in 1:1000
        s += f(i, 1, 1)
    end
return s
end

@btime loop_over_global()
@btime loop_over_global_witharg(fminus)



  32.400 μs (1976 allocations: 30.88 KiB)
  949.958 ns (0 allocations: 0 bytes)

Upvotes: 1

Related Questions