The following code does a whole bunch of allocations:
N = 10000000
A = randn(Float64, N)
b = 1.0
@show typeof(b)
@time for r = 1:N
b *= A[r]
end
Why is that? How can I write this in a way that doesn’t allocate ~ a gigabyte of memory? (In this particular case the right answer is prod, but this is a MWE we’ve run into in a more complicated context, where it’s not completely clear how to use prod.)
In particular:
julia> N = 10000000; A = randn(Float64, N); b = 1.0;@show typeof(b); @time for r = 1:N; b = b*A[r] end
typeof(b) = Float64
0.636152 seconds (50.00 M allocations: 915.513 MiB, 3.44% gc time, 0.94% compilation time)
julia> N = 10000000; A = randn(Float64, N); b = 1.0;@show typeof(b); @time for r = 1:N; b = b*A[r] end
typeof(b) = Float64
0.612025 seconds (50.00 M allocations: 915.512 MiB, 2.22% gc time)
don’t benchmark in the global scope. You’re seeing type instability since A is a non-type asserted global variable.
julia> N = 1000;
julia> A = randn(Float64, N);
julia> b = 1.0;
julia> @time for r = 1:N
b *= A[r]
end
0.007243 seconds (4.08 k allocations: 82.250 KiB, 98.37% compilation time)
julia> function myprod(A)
b = 1.0
for r = 1:length(A)
b *= A[r]
end
b
end
julia> @time myprod(A);
0.006203 seconds (3.66 k allocations: 203.109 KiB, 99.70% compilation time)
julia> @time myprod(A);
0.000006 seconds (1 allocation: 16 bytes)
Hmm. Yes, right, this is a very good point about my MWE. Our actual problem isn’t in global scope (I don’t think), so it’s not completely obvious how that’s going to play out, but I suppose there could be some similar type-instability effect.
Probably we should be wrapping the inside of the inner loop in a function anyway, which will help.