Consider the code at the bottom. The actual case is more complex, so something that does not depend on the definition of the function A would be appreciated.
This gives the time and allocation numbers below. Presumably the compiler sees through things when functionversion is called inside tryboth.
But there is memory allocation in the second call of functionversion in somethingelse.
- Is this caused by type instability? (unknown type signature of the function F)
- How should I rewrite the function somethingelse to avoid the memory allocation? Can generated functions be used here?
Thanks!
[ Info: time and memory used by regular version
0.007638 seconds
[ Info: time and memory used by clumsy version
0.004817 seconds
[ Info: memory allocated by clumsy version two
0.017712 seconds (224 allocations: 13.188 KiB, 56.71% compilation time)
0.007679 seconds (3 allocations: 48 bytes)
const T = Float64
const R = 1_000
const C = 10_000
function matrixversion( A::Matrix{T} )
rv = T(0.0)
for c ā axes(A,2)
for r ā axes(A,1)
rv += A[r,c]^2
end
end
rv
end
function functionversion( A::Function, rows::Int, cols::Int )
rv = T(0.0)
for c ā 1:cols
for r ā 1:rows
rv += A(r,c)^2
end
end
rv
end
function generateA( X::Matrix{T} )
A( r::Int, c::Int ) = X[r,c]
A
end
function tryboth(rows::Int, cols::Int)
X = randn( rows, cols )
A = generateA( X )
@info "time and memory used by regular version"
matrixversion( X )
@time matrixversion( X )
@info "time and memory used by clumsy version"
functionversion( A, rows, cols )
@time functionversion( A, rows, cols )
return A
end
function somethingelse( F::Function, rows::Int, cols::Int )
@time functionversion(F, rows, cols )
end
function testme(rows::Int, cols::Int)
A = tryboth( rows, cols )
@info "memory allocated by clumsy version two"
somethingelse( A, rows, cols )
somethingelse( A, rows, cols ) # how can I make this call use less memory?
end
testme(R,C)