Is there way to avoid `materialize` and `copy`?

cf https://github.com/JuliaLang/julia/issues/15276.

The problem is that inner functions that access outer variables might sometimes confuse the compiler into emitting “boxes”, i.e. essentially mutable structs, for these variables (when it cannot prove that it is save to omit the boxes).

I can never remember which patterns involving inner functions are OK and which are not. So my personal recommendation is to simply never ever use inner functions.

You can achieve anything doable by inner functions by one of the following two constructs:

  1. Often, it is possible to refactor into function LLH(pars, Nd, BM, transposedPsiDT). Most of the time, there is need to return a closure.
  2. Sometimes there is a genuine need to return a function: You need to generate a callback in order to conform to an API. Then you can manually create
struct LLH_locals{T<:AbstractMatrix} <: Function 
Nd::Int 
BM::T
...
end

function (locals::LLH_locals)(pars)
Nd = locals.Nd
...
end

If you make a closure, the compiler does something similar. But by being explicit, the allocations and the mutation semantics (inner function changes outer variable) become obvious. For example: Your inner function does not need to modify Nd, so we can pass its value into the closure. Otherwise, the outer function would need Nd_ = Ref(Nd_val), and always use Nd_[] to access the value; then the callable struct has a field Nd_::Ref{Int} pointing to the same memory location, and mutations are visible. If the compiler cannot prove that the inner function will never ever change the type of Nd, then the Ref must be untyped, and all code involving Nd is effectively interpreted, not compiled (but you call into compiled fast functions for things like matrix products). This is a “box”.

TL;DR: Closures in julia are hard to use efficiently. I personally view “implicit” closures as an experimental feature that is not yet mature enough for general use. But that might reflect my knowledge more than the state of the language.

1 Like