I am executing a code similar to the simple one below under the constraint that I cannot allocate anything before the loop due to some constraints of the calling function.
F = zeros(T, npoin, nelem)
As you can see, this reallocates memory at every loop iteration. I would like to avoid this and only allocate it the first time and reset the array to zero the following times.
The problem would not exist if I could allocate
F outside of the loop, but I cannot do that.
Is the a way to achieve this?
Can you modify
If so, even if not very good for practice, you can define in the global scope:
const global_F = zeros(T, npoin, nelem)
and then inside
F = fill!(global_F, zero(T))
but that comes with a lot of possible issues to care about (maintainability, races, etc.).
I can modify my_fun() and everything else before it’s called, but nothing out of the loop.
I can try this.
Feel free to add more options if anything else comes to mind. I don’t particularly like the const option of a global variable.
Can you explain a little bit this restriction?
(it would prevent even the definition of a global buffer, as I suggested - and complicates things quite a bit, since the variables created in each loop iteration are local to that iteration, so they woudn’t survive for the next iteration to be reused).
One alternative, make
my_fun a callable struct that carries its buffer:
F = fill!(my_fun.buffer, 0.0)
const my_fun = MyFun()
That is a little bit more clean that the global buffer, as at least the buffer is carried with the struct, but still has to be declared in the global scope (otherwise if you instantiate a new
MyFun object in each iteration of the loop, the buffer will be recreated the same).
If it == 1
X = ... # allocate
Doesn’t work, the
x is local to the loop iteration:
julia> function f()
for i in 1:2
if i == 1
x = zeros(2)
if i == 2
println(" iteration 2 ")
x .= 0.0
f (generic function with 1 method)
ERROR: UndefVarError: `x` not defined
@ Main ./REPL:8
 top-level scope
One would need to add something like
local x outside the loop, but that’s forbidden by the rules .
This is somewhat standard:
let F = zeros(T, npoin, nelem)
global function my_fun()
F .= zero(T)
but I would rather go for a callable struct.
@Imiq, the issue with the calling function is the following:
I am using DifferentialEquations.jl to solve
du/dt = RHS. This packge is used as defined below, where
u is the solution array and
rhs! is the function that calculates the RHS vector at every time step.
function rhs!() is the only function that I can control when it comes to allocations and array definitions etc. So, if
rhs!() allocates anything, it does so at every time iteration
prob = ODEProblem(rhs!,
solution = solve(prob, solver, dt=Δt...);
I cannot pass other than
function rhs!(), u, tspan, params to
You can preallocate everything in Params.
Note that you can provide any type you like there so an array or a tuple or your own struct are all fine
You can pass in pre-allocated arrays via
See also the PreallocationTools.jl package, which is specifically designed for use with
ODEProblem and similar.
Thank you for clarifying this. PreallocationTools.jl does exactly what I need!