Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid memory allocation in Julia?

Tags:

julia

Consider the following simple Julia code operating on four complex matrices:

n = 400

z = eye(Complex{Float64},n)
id = eye(Complex{Float64},n)
fc = map(x -> rand(Complex{Float64}), id)
cr = map(x -> rand(Complex{Float64}), id)

s = 0.1 + 0.1im

@time for j = 1:n
    for i = 1:n
        z[i,j] = id[i,j] - fc[i,j]^s * cr[i,j]
    end
end

The timing shows a few million memory allocations, despite all variables being preallocated:

0.072718 seconds (1.12 M allocations: 34.204 MB, 7.22% gc time)

How can I avoid all those allocations (and GC)?

like image 341
Alex Avatar asked Jan 20 '26 02:01

Alex


1 Answers

One of the first tips for performant Julia code is to avoid using global variables. This alone can cut the number of allocations by 7 times. If you must use globals, one way to improve their performance is to use const. Using const prevents change of type but change of value is possible with a warning.

consider this modified code without using functions:

const n = 400

z = Array{Complex{Float64}}(n,n)
const id = eye(Complex{Float64},n)
const fc = map(x -> rand(Complex{Float64}), id)
const cr = map(x -> rand(Complex{Float64}), id)

const s = 0.1 + 0.1im

@time for j = 1:n
    for i = 1:n
            z[i,j] = id[i,j] - fc[i,j]^s * cr[i,j]
    end
end 

The timing shows this result:

0.028882 seconds (160.00 k allocations: 4.883 MB)

Not only did the number of allocations get 7 times lower, but also the execution speed is 2.2 times faster.

Now let's apply the second tip for high performance Julia code; write every thing in functions. Writing the above code into a function z_mat(n):

function z_mat(n)
    z  = Array{Complex{Float64}}(n,n)
    id = eye(Complex{Float64},n)
    fc = map(x -> rand(Complex{Float64}), id)
    cr = map(x -> rand(Complex{Float64}), id)

    s = 1.0 + 1.0im

    @time for j = 1:n
        for i = 1:n
            z[i,j] = id[i,j] - fc[i,j]^s * cr[i,j]
        end
    end    
end

and running

z_mat(40)
  0.000273 seconds
@time z_mat(400)
  0.027273 seconds
  0.032443 seconds (429 allocations: 9.779 MB)

That is 2610 times fewer allocations than the original code for the whole function because the loop alone does zero allocations.

like image 117
AboAmmar Avatar answered Jan 22 '26 18:01

AboAmmar