# Help understanding allocation on scalar function and possible ways to avoid it

1. Can someone kindly explain me why the following function allocates memory? Is there a way to avoid it? On my machine it produces 14 allocations using inputs of `Float64`s (on Julia 6.1).
``````julia> using BenchmarkTools

julia> function energydistr_scalar(t11::T,t22::T,t33::T,t12::T,t13::T,t23::T,
d11::T,d22::T,d33::T,d12::T,d13::T,d23::T,
w12::T,w13::T,w23::T) where {T<:Number}

ɛ = t11 * d11 + t22 * d22 + t33 * d33 + 2.0*(t12 * d12 + t13*d13 + t23*d23)

dir11 = (d11*t11+d12*t12+d13*t13-t12*w12-t13*w13) - ɛ/3.
dir22 = (d12*t12+d22*t22+d23*t23+t12*w12-t23*w23) - ɛ/3.
dir33 = (d13*t13+d23*t23+d33*t33+t13*w13+t23*w23) - ɛ/3.
dir12 = 0.5*(d11*t12+d12*t11+d12*t22+d13*t23+d22*t12+d23*t13+t11*w12-t13*w23-t22*w12-t23*w13)
dir13 = 0.5*(d11*t13+d12*t23+d13*t11+d13*t33+d23*t12+d33*t13+t11*w13+t12*w23-t23*w12-t33*w13)
dir23 = 0.5*(d12*t13+d13*t12+d22*t23+d23*t22+d23*t33+d33*t23+t12*w13+t13*w12+t22*w23-t33*w23)

return ε,dir11,dir22,dir33,dir12,dir13,dir23
end
energydistr_scalar (generic function with 1 method)

julia> @benchmark energydistr_scalar(1.,2.,3.,4.,5.,5.,6.,7.,2.,8.,10.,11.,32.,23.,12.)
BenchmarkTools.Trial:
memory estimate:  224 bytes
allocs estimate:  14
--------------
minimum time:     102.095 ns (0.00% GC)
median time:      106.017 ns (0.00% GC)
mean time:        124.833 ns (6.61% GC)
maximum time:     1.772 μs (83.59% GC)
--------------
samples:          10000
evals/sample:     929
``````

My real usage of this calculation is the following function:

``````julia> function energydistr_part!(t11::T,t22::T,t33::T,t12::T,t13::T,t23::T,
d11::T,d22::T,d33::T,d12::T,d13::T,d23::T,
w12::T,w13::T,w23::T,
dir11::T,dir22::T,dir33::T,dir12::T,dir13::T,dir23::T,
ɛ::T) where {T<:Vector{<:Number}}

@inbounds for i in 1:length(d11)
ɛ[i] = t11[i] * d11[i] + t22[i] * d22[i] + t33[i] * d33[i] + 2.0*(t12[i] * d12[i] + t13[i]*d13[i] + t23[i]*d23[i])

dir11[i] = (d11[i]*t11[i]+d12[i]*t12[i]+d13[i]*t13[i]-t12[i]*w12[i]-t13[i]*w13[i]) - ɛ[i]/3.
dir22[i] = (d12[i]*t12[i]+d22[i]*t22[i]+d23[i]*t23[i]+t12[i]*w12[i]-t23[i]*w23[i]) - ɛ[i]/3.
dir33[i] = (d13[i]*t13[i]+d23[i]*t23[i]+d33[i]*t33[i]+t13[i]*w13[i]+t23[i]*w23[i]) - ɛ[i]/3.
dir12[i] = 0.5*(d11[i]*t12[i]+d12[i]*t11[i]+d12[i]*t22[i]+d13[i]*t23[i]+d22[i]*t12[i]+d23[i]*t13[i]+t11[i]*w12[i]-t13[i]*w23[i]-t22[i]*w12[i]-t23[i]*w13[i])
dir13[i] = 0.5*(d11[i]*t13[i]+d12[i]*t23[i]+d13[i]*t11[i]+d13[i]*t33[i]+d23[i]*t12[i]+d33[i]*t13[i]+t11[i]*w13[i]+t12[i]*w23[i]-t23[i]*w12[i]-t33[i]*w13[i])
dir23[i] = 0.5*(d12[i]*t13[i]+d13[i]*t12[i]+d22[i]*t23[i]+d23[i]*t22[i]+d23[i]*t33[i]+d33[i]*t23[i]+t12[i]*w13[i]+t13[i]*w12[i]+t22[i]*w23[i]-t33[i]*w23[i])
end
return nothing
end
energydistr_part! (generic function with 1 method)

julia> input = [rand(512) for i = 1:22];

julia> @benchmark energydistr_part!(input...)
BenchmarkTools.Trial:
memory estimate:  112.00 KiB
allocs estimate:  7168
--------------
minimum time:     60.250 μs (0.00% GC)
median time:      62.518 μs (0.00% GC)
mean time:        74.095 μs (5.25% GC)
maximum time:     1.343 ms (83.13% GC)
--------------
samples:          10000
evals/sample:     1

``````

Which produces `14*length(d11)` allocations. And since I using it with Arrays with lengths around 1024^3 I am already almost out of memory…

This is fixed on 0.7. I think it has something to do with the length of your terms. A quick check seems to confirm this: just delete enough terms on all lines and the allocations go away. I think as a work-around you can use temporary variable.

2 Likes
4 Likes

That was it .
I’m ashamed that in my look-up I failed to find the answer which was posted just yesterday

1 Like