Consider the following example:
module structs
mutable struct testStruct
x::Array{Int64,2}
end
end
function innerFunc(s::structs.testStruct)
s.x[1:2] .= s.x[3:4]
end
function structTest!(s::structs.testStruct, n)
for i = 1:n
innerFunc(s)
end
println(s.x)
end
The memory allocations, as I increase n
, increase as well. I think that's because in each iteration, I'm creating an allocation for s.x[3:4]
. I can avoid this by using a loop:
function innerFunc(s::structs.testStruct)
for i = 1:2
s.x[i] .= s.x[i+2]
end
end
function structTest!(s::structs.testStruct, n)
for i = 1:n
innerFunc(s)
end
println(s.x)
end
However, I don't like loops because the syntax is burdensome. Is there a way to avoid it? In each iteration, I want to modify the first and second elements of s.x
without increasing memory allocations as I increase n
since I'm not creating anything new.
UPDATE: In response to DNF, I tried to use @view
:
module structs
mutable struct testStruct
x::Array{Int64,2}
end
end
function innerfunc!(s::structs.testStruct)
s.x[1:2] .= view(s.x, 3:4)
end
function structTest!(s::structs.testStruct, n)
for i = 1:n
innerfunc!(s)
end
println(s.x)
end
This is what I got:
@time structTest!(structs.testStruct([1 2 3 4]),33)
0.000112 seconds (202 allocations: 7.938 KiB)
@time structTest!(structs.testStruct([1 2 3 4]),330)
0.000126 seconds (1.69 k allocations: 68.266 KiB)
I want the allocations to stay invariant to n
.
As @DNF noted, using views should have solved the problem, but because views are not immutable, then there is a small memory cost, which in usual applications is immaterial.
So essentially, you have to use a for
loop. To make it look a bit more vectorized, Dahua Lin's Devectorized.jl package comes to the rescue:
# Pkg.add("Devectorized.jl")
using Devectorized
function innerfunc!(s::structs.testStruct)
@devec s.x[1:2] = s.x[3:4]
end
and you are good to go:
julia> @time structTest!(structs.testStruct([1 2 3 4]),3300)
0.000299 seconds (40 allocations: 1.641 KiB)
julia> @time structTest!(structs.testStruct([1 2 3 4]),330000)
0.001209 seconds (40 allocations: 1.641 KiB)