For the following code:
function run0(x, V, n)
for i=1:n
V(x);
end
end
function vA(x,A)
v = 0.5 * A * x^2;
return v
end
v1 = x-> vA(x,2);
x0 = rand();
@time run0(x0, v1, 10)
@time run0(x0, v1, 10)
@time run0(x0, v1, 100)
@time run0(x0, v1, 1000)
@time run0(x0, v1, 10000)
A = 2.0;
v2 = x-> vA(x,A);
@time run0(x0, v2, 10)
@time run0(x0, v2, 10)
@time run0(x0, v2, 100)
@time run0(x0, v2, 1000)
@time run0(x0, v2, 10000)
I find that the latter function, v2
, is allocating additional memory at each iteration:
0.005096 seconds (1.54 k allocations: 83.864 KiB)
0.000003 seconds (4 allocations: 160 bytes)
0.000002 seconds (4 allocations: 160 bytes)
0.000002 seconds (4 allocations: 160 bytes)
0.000001 seconds (4 allocations: 160 bytes)
0.007968 seconds (1.65 k allocations: 88.158 KiB)
0.000004 seconds (34 allocations: 640 bytes)
0.000008 seconds (304 allocations: 4.844 KiB)
0.000055 seconds (3.00 k allocations: 47.031 KiB)
0.000514 seconds (30.00 k allocations: 468.906 KiB)
Looking at the @code_warntype
, there are clearly type instabilities in the latter function:
julia> @code_warntype v2(x0)
Variables:
#self# <optimized out>
x::Float64
v <optimized out>
Body:
begin
SSAValue(0) = Main.A
$(Expr(:inbounds, false))
# meta: location /Users/gideonsimpson/code/weighted_ensemble/forpost3.jl vA 9
# meta: location operators.jl * 424
SSAValue(1) = ((0.5 * SSAValue(0))::Any * (Base.mul_float)(x::Float64, x::Float64)::Float64)::Any
# meta: pop location
# meta: pop location
$(Expr(:inbounds, :pop))
return SSAValue(1)
end::Any
But I’m unclear on why these are occurring and how best to write code to avoid them.