From 7b0dbeaa2f7b20802f50abb5c514c63249c667f6 Mon Sep 17 00:00:00 2001 From: singhharsh1708 Date: Wed, 28 Oct 2026 04:35:27 +0530 Subject: [PATCH 1/4] Run threaded stages serially inside another threaded region --- lib/OrdinaryDiffEqCore/src/misc_utils.jl | 4 ++++ lib/OrdinaryDiffEqPRK/test/prk_convergence.jl | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/lib/OrdinaryDiffEqCore/src/misc_utils.jl b/lib/OrdinaryDiffEqCore/src/misc_utils.jl index aca3796fcd..942b117a2b 100644 --- a/lib/OrdinaryDiffEqCore/src/misc_utils.jl +++ b/lib/OrdinaryDiffEqCore/src/misc_utils.jl @@ -124,6 +124,10 @@ isthreaded(::BaseThreads) = true isthreaded(::PolyesterThreads) = true @inline function _threaded_execute(f, ::Union{BaseThreads, Bool}, range) + if ccall(:jl_in_threaded_region, Cint, ()) != 0 + foreach(f, range) + return nothing + end return Threads.@threads :static for i in range f(i) end diff --git a/lib/OrdinaryDiffEqPRK/test/prk_convergence.jl b/lib/OrdinaryDiffEqPRK/test/prk_convergence.jl index 2f1d5c4d0d..fb9411e9e6 100644 --- a/lib/OrdinaryDiffEqPRK/test/prk_convergence.jl +++ b/lib/OrdinaryDiffEqPRK/test/prk_convergence.jl @@ -17,3 +17,16 @@ testTol = 0.2 sim3 = test_convergence(dts2, prob, KuttaPRK2p5(threading = false)) @test sim3.𝒪est[:l∞] ≈ 5 atol = testTol end + +@testset "Threaded stages inside another threaded loop" begin + prob_iip = ODEProblem((du, u, p, t) -> (du .= -u), [1.0, 2.0], (0.0, 1.0)) + prob_oop = ODEProblem((u, p, t) -> -u, 1.0, (0.0, 1.0)) + for prob in (prob_iip, prob_oop) + serial = solve(prob, KuttaPRK2p5(threading = false); dt = 0.1) + sols = Vector{Any}(undef, 2) + Threads.@threads for i in 1:2 + sols[i] = solve(prob, KuttaPRK2p5(threading = true); dt = 0.1) + end + @test all(sol -> sol.u == serial.u, sols) + end +end From 99050301fe43b41aab6554854f4c9c4708b01190 Mon Sep 17 00:00:00 2001 From: singhharsh1708 Date: Sun, 1 Nov 2026 20:53:33 +0530 Subject: [PATCH 2/4] Run nested-threads PRK regression from runtests.jl --- lib/OrdinaryDiffEqPRK/test/prk_convergence.jl | 13 ------------- lib/OrdinaryDiffEqPRK/test/runtests.jl | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/lib/OrdinaryDiffEqPRK/test/prk_convergence.jl b/lib/OrdinaryDiffEqPRK/test/prk_convergence.jl index fb9411e9e6..2f1d5c4d0d 100644 --- a/lib/OrdinaryDiffEqPRK/test/prk_convergence.jl +++ b/lib/OrdinaryDiffEqPRK/test/prk_convergence.jl @@ -17,16 +17,3 @@ testTol = 0.2 sim3 = test_convergence(dts2, prob, KuttaPRK2p5(threading = false)) @test sim3.𝒪est[:l∞] ≈ 5 atol = testTol end - -@testset "Threaded stages inside another threaded loop" begin - prob_iip = ODEProblem((du, u, p, t) -> (du .= -u), [1.0, 2.0], (0.0, 1.0)) - prob_oop = ODEProblem((u, p, t) -> -u, 1.0, (0.0, 1.0)) - for prob in (prob_iip, prob_oop) - serial = solve(prob, KuttaPRK2p5(threading = false); dt = 0.1) - sols = Vector{Any}(undef, 2) - Threads.@threads for i in 1:2 - sols[i] = solve(prob, KuttaPRK2p5(threading = true); dt = 0.1) - end - @test all(sol -> sol.u == serial.u, sols) - end -end diff --git a/lib/OrdinaryDiffEqPRK/test/runtests.jl b/lib/OrdinaryDiffEqPRK/test/runtests.jl index 1a477da516..b0dd78b142 100644 --- a/lib/OrdinaryDiffEqPRK/test/runtests.jl +++ b/lib/OrdinaryDiffEqPRK/test/runtests.jl @@ -23,6 +23,20 @@ end @test !any(Base.isexported.(Ref(OrdinaryDiffEqPRK), internal)) end +@time @safetestset "Threaded stages inside another threaded loop" begin + using OrdinaryDiffEqPRK, Test + prob_iip = ODEProblem((du, u, p, t) -> (du .= -u), [1.0, 2.0], (0.0, 1.0)) + prob_oop = ODEProblem((u, p, t) -> -u, 1.0, (0.0, 1.0)) + for prob in (prob_iip, prob_oop) + serial = solve(prob, KuttaPRK2p5(threading = false); dt = 0.1) + sols = Vector{Any}(undef, 2) + Threads.@threads for i in 1:2 + sols[i] = solve(prob, KuttaPRK2p5(threading = true); dt = 0.1) + end + @test all(sol -> sol.u == serial.u, sols) + end +end + # Run QA tests (AllocCheck, JET, Aqua) - skip on pre-release Julia # Allocation tests must run before JET because JET's static analysis # invalidates compiled code and causes spurious runtime allocations. From bf7691efe3b0d08112a5812873a88e7c4d646dbd Mon Sep 17 00:00:00 2001 From: singhharsh1708 Date: Mon, 2 Nov 2026 00:56:43 +0530 Subject: [PATCH 3/4] Compare nested PRK solves with a top-level threaded solve --- lib/OrdinaryDiffEqPRK/test/runtests.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/OrdinaryDiffEqPRK/test/runtests.jl b/lib/OrdinaryDiffEqPRK/test/runtests.jl index b0dd78b142..6cfa9b24ea 100644 --- a/lib/OrdinaryDiffEqPRK/test/runtests.jl +++ b/lib/OrdinaryDiffEqPRK/test/runtests.jl @@ -28,12 +28,12 @@ end prob_iip = ODEProblem((du, u, p, t) -> (du .= -u), [1.0, 2.0], (0.0, 1.0)) prob_oop = ODEProblem((u, p, t) -> -u, 1.0, (0.0, 1.0)) for prob in (prob_iip, prob_oop) - serial = solve(prob, KuttaPRK2p5(threading = false); dt = 0.1) + threaded = solve(prob, KuttaPRK2p5(threading = true); dt = 0.1) sols = Vector{Any}(undef, 2) Threads.@threads for i in 1:2 sols[i] = solve(prob, KuttaPRK2p5(threading = true); dt = 0.1) end - @test all(sol -> sol.u == serial.u, sols) + @test all(sol -> sol.u == threaded.u, sols) end end From 1c61b6f1325634cc5a22a8cb0bd8a02b48b8f2b8 Mon Sep 17 00:00:00 2001 From: singhharsh1708 Date: Wed, 4 Nov 2026 00:29:25 +0530 Subject: [PATCH 4/4] Bump OrdinaryDiffEqCore to 4.20.2 --- lib/OrdinaryDiffEqCore/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/OrdinaryDiffEqCore/Project.toml b/lib/OrdinaryDiffEqCore/Project.toml index aac68e41f4..2e52fa5cf4 100644 --- a/lib/OrdinaryDiffEqCore/Project.toml +++ b/lib/OrdinaryDiffEqCore/Project.toml @@ -1,7 +1,7 @@ name = "OrdinaryDiffEqCore" uuid = "bbf590c4-e513-4bbe-9b18-05decba2e5d8" authors = ["ParamThakkar123 "] -version = "4.20.1" +version = "4.20.2" [deps] ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b"