# DiffEqGPU - error calling solve() for SDE driven by 2 correlated Brownians

**URL:** <https://discourse.julialang.org/t/diffeqgpu-error-calling-solve-for-sde-driven-by-2-correlated-brownians/136118>\
**Category:** GPU\
**Created:** [March 10, 2026, 2:58pm UTC](https://discourse.julialang.org/t/diffeqgpu-error-calling-solve-for-sde-driven-by-2-correlated-brownians/136118 "2026-03-10T14:58:46Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![sob](https://avatars.discourse-cdn.com/v4/letter/s/65b543/32.png) [@sob](https://discourse.julialang.org/u/sob)\
**Post date:** [March 10, 2026, 2:58pm UTC](https://discourse.julialang.org/t/diffeqgpu-error-calling-solve-for-sde-driven-by-2-correlated-brownians/136118/1 "2026-03-10T14:58:46Z")

</div>

Julia version: latest stable 1.12.5 on Linux, up to date on packages

I have a 2D SDE driven by 2 Brownians with correlation `ρ`, and I’m trying to solve on the GPU using `SciML`. I should note that I am separately able to Monte Carlo my drift and diffusion fine on the GPU (without `SciML`, using just `CUDA`), and I’m also able to solve the `EnsembleProb` on the CPU with `EnsembleThreads()`. But I’m struggling to get it to `solve` with `DiffEqGPU`.

Here’s the same code that fails when running `solve`:

```julia-auto
using DifferentialEquations, DiffEqGPU, CUDA, Statistics, StaticArrays

function drift!(du, u, p, t)
    du[1] = 0.0
    du[2] = 0.0
end

function diffusion!(du, u, p, t)
    β, ν, ρ = p
    du[1, 1] = σ * u[1]^β
    du[1, 2] = 0.0

    # correlation handled w Cholesky
    du[2, 1] = ν * u[2] * ρ
    du[2, 2] = ν * u[2] * sqrt(1.0 - ρ^2)
end

function test()

    β = 0.5
    ν = 0.4 
    ρ = -0.3
    F0 = 0.03
    α = 0.20
    T = 1.0
    n_paths = 100_000
 
    u0 = @SVector Float32[F0, α]
    tspan = (0.0, T)
    p = @SVector Float32[β, ν, ρ]

    noise_rate_prototype = @SMatrix zeros(Float32, 2, 2)

    prob = SDEProblem(
        drift!,
        diffusion!,
        u0,
        tspan,
        p;
        noise_rate_prototype = noise_rate_prototype
    )

    ensemble_prob = EnsembleProblem(prob)

    sol = solve(
        ensemble_prob,
        GPUTsit5(),
        DiffEqGPU.EnsembleGPUKernel(CUDA.CUDABackend());
        dt = T / 300,
        trajectories = n_paths,
        save_everystep = false,
        save_start = false,
        adaptive = false
    )

    return sol

end

test()

```

And I get this error when running:

```julia-auto
ERROR: UndefVarError: `kernel` not defined in local scope
Suggestion: check for an assignment to a local variable that shadows a global of the same name.
Stacktrace:
 [1] vectorized_solve(probs::CuArray{…}, prob::SDEProblem{…}, alg::GPUTsit5; dt::Float64, saveat::Nothing, save_everystep::Bool, debug::Bool, kwargs::@Kwargs{…})
   @ DiffEqGPU ~/.julia/packages/DiffEqGPU/ExLjA/src/ensemblegpukernel/lowerlevel_solve.jl:166
 [2] batch_solve_up_kernel(ensembleprob::EnsembleProblem{…}, probs::Vector{…}, alg::GPUTsit5, ensemblealg::DiffEqGPU.EnsembleGPUKernel{…}, I::UnitRange{…}, adaptive::Bool; kwargs::@Kwargs{…})
   @ DiffEqGPU ~/.julia/packages/DiffEqGPU/ExLjA/src/solve.jl:378
 [3] batch_solve(ensembleprob::EnsembleProblem{…}, alg::GPUTsit5, ensemblealg::DiffEqGPU.EnsembleGPUKernel{…}, I::UnitRange{…}, adaptive::Bool; kwargs::@Kwargs{…})
   @ DiffEqGPU ~/.julia/packages/DiffEqGPU/ExLjA/src/solve.jl:221
 [4] macro expansion
   @ ./timing.jl:461 [inlined]
 [5] __solve(ensembleprob::EnsembleProblem{…}, alg::GPUTsit5, ensemblealg::DiffEqGPU.EnsembleGPUKernel{…}; trajectories::Int64, batch_size::Int64, unstable_check::Function, adaptive::Bool, kwargs::@Kwargs{…})
   @ DiffEqGPU ~/.julia/packages/DiffEqGPU/ExLjA/src/solve.jl:69
 [6] solve(::EnsembleProblem{…}, ::GPUTsit5, ::Vararg{…}; kwargs::@Kwargs{…})
   @ SciMLBase ~/.julia/packages/SciMLBase/eTBDr/src/ensemble/basic_ensemble_solve.jl:387
 [7] test()
   @ Main ~/workspace/test/scratchpad/mwe.jl:220
 [8] top-level scope
   @ ~/workspace/test/scratchpad/mwe.jl:236
Some type information was truncated. Use `show(err)` to see complete types.

```

The suggestion provided by the error message doesn’t seem relevant in this case.

Curious if anybody has ever encountered something similar?

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [March 10, 2026, 10:52pm UTC](https://discourse.julialang.org/t/diffeqgpu-error-calling-solve-for-sde-driven-by-2-correlated-brownians/136118/2 "2026-03-10T22:52:27Z")

</div>

> [@sob](#):
>
> `GPUTsit5()`

This is not a solver for SDEs. You need to use a solver for SDEs. Not sure why that’s the error you get but yeah it’s just a missing dispatch.

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [March 10, 2026, 11:28pm UTC](https://discourse.julialang.org/t/diffeqgpu-error-calling-solve-for-sde-driven-by-2-correlated-brownians/136118/4 "2026-03-10T23:28:29Z")

</div>

`GPUEM` and `GPUSIEA` are the documented methods for this. Did you give them a try?

> **[Specialized Solvers - EnsembleGPUKernel · DiffEqGPU.jl](https://docs.sciml.ai/DiffEqGPU/stable/manual/ensemblegpukernel/#specialsolvers)**
>
> A massively-parallel ensemble algorithm which generates a unique GPU kernel for the entire ODE which is then executed. This leads to a very low overhead GPU code generation, but imparts some extra limitations on the use. | Documentation for...

---

<div class="post-metadata">

**Author:** ![sob](https://avatars.discourse-cdn.com/v4/letter/s/65b543/32.png) [@sob](https://discourse.julialang.org/u/sob)\
**Post date:** [March 11, 2026, 1:22am UTC](https://discourse.julialang.org/t/diffeqgpu-error-calling-solve-for-sde-driven-by-2-correlated-brownians/136118/5 "2026-03-11T01:22:42Z")

</div>

Thanks Chris. I had a couple other issues in the code: drift and diffusion had to change to non inplace functions, and return stack allocated variables. I figured that part by looking at the documented API example for ODE on GPU, as examples for SDE on GPU are harder to find.

But doing that and using `GPUEM()` did the trick, thank you.

It also seems using ensemblealg as a kwarg instead of positional was silently sending me straight to the CPU (multithread) instead of GPU, which added to the confusion.

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [March 11, 2026, 1:27am UTC](https://discourse.julialang.org/t/diffeqgpu-error-calling-solve-for-sde-driven-by-2-correlated-brownians/136118/6 "2026-03-11T01:27:16Z")

</div>

Yeah it looks like we need a bit better validation on the args here. Could you open an issue? A few proactive error messages could have made this 200x easier.

---

<div class="post-metadata">

**Author:** ![sob](https://avatars.discourse-cdn.com/v4/letter/s/65b543/32.png) [@sob](https://discourse.julialang.org/u/sob)\
**Post date:** [March 11, 2026, 6:53pm UTC](https://discourse.julialang.org/t/diffeqgpu-error-calling-solve-for-sde-driven-by-2-correlated-brownians/136118/7 "2026-03-11T18:53:57Z")

</div>

Will do as soon as I get a chance, thanks Chris

---

<div class="post-metadata">

**Author:** ![sob](https://avatars.discourse-cdn.com/v4/letter/s/65b543/32.png) [@sob](https://discourse.julialang.org/u/sob)\
**Post date:** [March 16, 2026, 1:15am UTC](https://discourse.julialang.org/t/diffeqgpu-error-calling-solve-for-sde-driven-by-2-correlated-brownians/136118/8 "2026-03-16T01:15:57Z")

</div>

> <https://github.com/SciML/DifferentialEquations.jl/issues/1130>
>
> The issue arose when trying to use solve with an EnsembleProblem on the GPU.
> 
> Us…ing the positional arguments but ensemblealg as a kwarg made the function default back to CPU instead of GPU, masking the face that the solver I was using was not fit for the GPU, and debugging of my function call harder.
> 
> 
> It would be more friendly to the user if at least passing a positional arg as a kwarg threw a warning or error, making it visible to the user that they're misusing the function.

@ChrisRackauckas hopefully this is descriptive enough. Let me know if I can help in any other way. Much appreciated.

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [March 17, 2026, 12:39pm UTC](https://discourse.julialang.org/t/diffeqgpu-error-calling-solve-for-sde-driven-by-2-correlated-brownians/136118/9 "2026-03-17T12:39:03Z")

</div>

That is great, thank you.
