Using the result of NonlinearSolve.jl allocates memory

I’m using the following code to try and understand how broadcasting and allocation work in Julia:

using NonlinearSolve

function nonlin()
    nonlinprob(x, p) = return x - 3
    prob = NonlinearProblem(nonlinprob, 2.)
    sol = solve(prob, SimpleNewtonRaphson()).u

    a = zeros(100)
    b = range(1, 2, 100)

    @time a .= sol
    @time a .= sol .+ b
    @time a .= sol .+ b.^2 .+ b.^3
    @time a[1] = sol + b[1]^2
    @time a[1] = sol
    @time a .= 1.5 .+ b.^2 .+ b.^3
    nothing
end

nonlin()

My (perhaps naïve) assumption was that none of these would allocate as nothing is created. However, the output is

  0.000007 seconds (1 allocation: 16 bytes)
  0.000006 seconds (2 allocations: 128 bytes)
  0.000009 seconds (8 allocations: 416 bytes)
  0.000006 seconds (1 allocation: 16 bytes)
  0.000001 seconds
  0.000000 seconds

meaning that only the last two don’t allocate. Now this lead me to believe that there might be some type instability with the extracted solution, but doing something like a = zeros(eltype(sol), 100) results in the same amount and size of allocations (apart from the last for which the allocations of course increase). Furthermore, print(eltype(sol)) gives Float64, as expected. What could cause these allocations in this code?

If you do prob = NonlinearProblem{false}(nonlinprob, 2.) is it fine?

Yes, if I do that the allocations disappear. What does adding the {false} do if I may ask? Searching I see it in a few examples in the NonlinearSolve.jl FAQ but no explanation really.

Directly sets iip=false, i.e. out of place. That should be compiler inferred but something in the later versions seems to be going on. I need to handle that.

1 Like