Abdul Haseeb
Abdul Haseeb

Reputation: 73

Passing struct object in function and changing it allocates memory in Julia. Why?

The code I am playing around with is given below:

Base.@kwdef struct cyl_struct
    n::Int64
    a::Array{Float64} =   Array{Float64}(undef,n,2);
end

function adder(cyl)
    for i in 1:cyl.n
        cyl.a[i,1] = 1.0;
    end
end

function adder2(a,n)
    for i in 1:n
        a[i,1] = 1.0;
    end
end

n = 1000;

geom = cyl_struct(n=n);

@btime adder(geom)
@btime adder2(geom.a, geom.n)

Running this code gives me the output:

  23.700 μs (489 allocations: 7.64 KiB)
  594.444 ns (3 allocations: 80 bytes)

My question is: when I pass the structure as argument and make changes inside it, it allocates memory, but when I pass the individual arrays as arguments, it doesn't allocate memory. Why? How can I pass the structure object in a way that it doesn't allocate memory if modified inside function? Please, I would like your help. Thanks in advance.

Upvotes: 0

Views: 177

Answers (1)

Bill
Bill

Reputation: 6086

The code is replacing the a member of the struct. You can reference the member's elements via a broadcasted assignment instead:

using BenchmarkTools

Base.@kwdef struct cyl_struct
    n::Int64
    a::Array{Float64} = Array{Float64}(undef, n, 2);
end

function adder(cyl)
    for i in 1:n
        cyl.a[i, 1] = 1.0
    end
end

function adder1b(cyl)
    cyl.a[1:cyl.n, 1] .= 1.0
end

function adder2(a, n)
    for i in 1:n
        a[i, 1] = 1.0
    end
end

n = 1000
geom = cyl_struct(n = n);

@btime adder(geom)
@btime adder1b(geom)
@btime adder2(geom.a, geom.n)

Yields

92.600 μs (1979 allocations: 46.56 KiB)
229.712 ns (2 allocations: 96 bytes)
686.755 ns (3 allocations: 80 bytes)

Upvotes: 1

Related Questions