ITADN

Possible type instability in `BVP.BVProblem()` and `BVP.solve()`

#454Openabcdvvvv 创建于 2026-03-20
A
abcdvvvvcommented
This issue originates from a Julia Discourse thread: https://discourse.julialang.org/t/boundaryvaluediffeq-jl-reducing-allocations/136255 I noticed what appears to be type instability in both `BVP.BVProblem()` and `BVP.solve()`, which may affect solver performance. ## Minimal reproducible example ```julia import BoundaryValueDiffEq as BVP using Cthulhu function distribution_fun_test!(dydt::AbstractVector{T}, y::AbstractVector{T}, p::Any, t::Float64) where {T<:Real} y1, y2, y3, y4 = y dydt[1] = 0.001 * y2 dydt[2] = 10 * y1 dydt[3] = -0.03 * y2 + 0.0001 * y4 dydt[4] = 10 * y3 uptake = 0.1 * y3 / (1000 * y3 + 1) dydt[3] += uptake end function distribution_bc_test!(residual::AbstractVector{}, u::Any, p::Any, t::Vector{Float64}) residual[1] = (u[4, end] - 0.001) residual[2] = u[1, end] residual[3] = -u[3, end] residual[4] = u[1, 1] end function test_solve() L = 100.0 mesh_size = 500 tspan::Tuple{Float64, Float64} = (0.0, Float64(L)) y_initial::Vector{Float64} = [1, 0.001 / 0.03, 1, 0.001] bvp_problem = BVP.BVProblem( distribution_fun_test!, distribution_bc_test!, y_initial, tspan, ) @time BVP.solve(bvp_problem, BVP.MIRK5(); adaptive = false, dt = Float64(L / mesh_size)) @time BVP.solve(bvp_problem, BVP.MIRK5(); adaptive = false, dt = Float64(L / mesh_size)) end @descend test_solve() ``` ## Output ```julia > @descend test_solve() test_solve() @ Main REPL[5]:1 1 function test_solve()::Any 2 L::Core.Const(100.0) = 100.0::Core.Const(100.0) 3 mesh_size::Core.Const(500) = 500::Core.Const(500) 4 (tspan::Core.Const((0.0, 100.0))::Tuple{Float64, Float64})::Core.Const(true) = (0.0, Float64(L::Core.Const(100.0))::Core.Const(100.0))::Core.Const((0.0, 100.0)) 6 6 (y_initial::Vector{Float64}::Vector{Float64})::Core.Const(true) = [1, (0.001/0.03)::Core.Const(0.03333333333333333), 1, 0.001]::Vector{Float64} 8 8 bvp_problem::Any = BVP.BVProblem::Type{SciMLBase.BVProblem}(distribution_fun_test!::Core.Const(Main.distribution_fun_test!), 9 distribution_bc_test!::Core.Const(Main.distribution_bc_test!), 10 y_initial::Vector{Float64}, tspan::Core.Const((0.0, 100.0)))::Any 11 12 @time BVP.solve::Core.Const(CommonSolve.solve)(bvp_problem::Any, BVP.MIRK5::Type{BoundaryValueDiffEqMIRK.MIRK5}()::Core.Const(MIRK5(jac_alg = BVPJacobianAlgorithm(), defect_threshold = 0.1, max_num_subintervals = 3000)); adaptive = false, dt=Float64((L::Core.Const(100.0)/mesh_size::Core.Const(500))::Float64)::Tuple{Any, Float64, Int64, Float64, Base.GC_Diff, Int64, Float64, Float64}::NamedTuple{(:value, :time, :bytes, :gctime, :gcstats, :lock_conflicts, :compile_time, :recompile_time), <:Tuple{Any, Float64, Int64, Float64, Base.GC_Diff, Int64, Float64, Float64}})::Any 13 @time BVP.solve::Core.Const(CommonSolve.solve)(bvp_problem::Any, BVP.MIRK5::Type{BoundaryValueDiffEqMIRK.MIRK5}()::Core.Const(MIRK5(jac_alg = BVPJacobianAlgorithm(), defect_threshold = 0.1, max_num_subintervals = 3000)); adaptive = false, dt=Float64((L::Core.Const(100.0)/mesh_size::Core.Const(500))::Float64)::Tuple{Any, Float64, Int64, Float64, Base.GC_Diff, Int64, Float64, Float64}::NamedTuple{(:value, :time, :bytes, :gctime, :gcstats, :lock_conflicts, :compile_time, :recompile_time), <:Tuple{Any, Float64, Int64, Float64, Base.GC_Diff, Int64, Float64, Float64}})::Any 14 end ``` ## Observation From the `@descend` output: * `bvp_problem` is inferred as `Any` * `test_solve()` is inferred as returning `Any` * consequently, the return value of `BVP.solve(...)` is reckoned to be `Any` This suggests that `BVP.BVProblem()` and `BVP.solve()` may be type-unstable in this case. Since this can introduce additional allocations and hurt performance, I thought it would be worth reporting. ## Environment * Ubuntu 25.10 * Julia 1.12.5
0 条评论