Use of anonymous functions has high compilation time

Hi everyone,

I am currently struggling with the usage of anonymous functions. I have a function dirichlet! that takes a function as one of its inputs. The function returns a value based on the position x.

function dirichlet!(f, K::SparseMatrixCSC{Tv,Ti}, F::Vector{Tv}, nodes::Matrix{Tv}, elements::GFMat{<:Int}, axis::NTuple{N,<:Int}) where {Ti,Tv,N}
  dofAxes = Vector{Int}()
  for i in eachindex(axis)
    if axis[i] > 0
      push!(dofAxes, i)
    end
  end
  for i in axes(elements, 1)
    e = elements[i]
    for n in e
      dofs = dofAxes .+ (n - 1) * N
      x::Vector{Tv} = nodes[1:N, n]
      pval::NTuple{N,Tv} = f(x)
      _prescribef!(dofs, K, F, pval)
      _zerorow!(dofs, K)
      _zerocolumn!(dofs, K)
      K[dofs, dofs] .= 1.0
    end
  end
  dropzeros!(K)
  return F
end

However, when I actually use the function there is an almost 100% compilation time each time i run the code. If I set pval manually the compilation time goes back to 0%.

I run the code like this:

  fr = (::Vector{Float64}) -> (0.0, 0.0)
  F = dirichlet!(fl, K, F, mesh.nodes, left, (1, 0))

I have tried different methods of inputting the function, and changing the input type of function, but nothing seemed to work.

Any help would be greatly appreciated.

Kind regards,
Thomas

Your code isn’t reproducible (where does GFMat come from?) but I suspect you’re hitting the infamous heuristic for avoiding specialization. When you pass a function f as argument to another function g, the compiler does not specialize the resulting code by default, which means it cannot infer what f(x) will be inside g. This also explains why setting pval manually resolves it. To force specialization, just add a type annotation f::F to the function signature. Does it work?

1 Like

I already tried adding the type to the function, but that didn’t change a lot.

However, I realised that I was not really correctly benchmarking. The compilation time was almost 100% for low DOF problems, but for higher DOF problems the _zerorow! function is the bottleneck. My bad I should have check better before posting. Thanks anyways for helping.

Regardless of problem size, compilation time should account for exactly 0% after the first run, otherwise you have some type-instabilities. Did you use BenchmarkTools.jl for benchmarking? Did you interpolate the variables?

1 Like