# Benchmark AutoDiff on simple 1D diffusion operator

**URL:** https://discourse.julialang.org/t/benchmark-autodiff-on-simple-1d-diffusion-operator/123885
**Category:** General Usage
**Created:** [December 16, 2024, 2:05pm UTC](https://discourse.julialang.org/t/benchmark-autodiff-on-simple-1d-diffusion-operator/123885 "2024-12-16T14:05:01Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![yolhan\_mannes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yolhan_mannes/32/220485_2.png) [@yolhan\_mannes](https://discourse.julialang.org/u/yolhan_mannes)
#### Post date: [December 16, 2024, 2:05pm UTC](https://discourse.julialang.org/t/benchmark-autodiff-on-simple-1d-diffusion-operator/123885/1 "2024-12-16T14:05:01Z")

</div>

Just sharing a small benchmark in case someone finds it useful in the future—it’s about evaluating the Jacobian of a simple diffusion operator.

```julia
uin() = 0.0
uout() = 0.0
function Diffusion(u)
    du = zero(u)
    for i in eachindex(du,u)
        if i == 1
            ug = uin()
            ud = u[i+1]
        elseif i == length(u)
            ug = u[i-1]
            ud = uout()
        else
            ug = u[i-1]
            ud = u[i+1] 
        end
        du[i] = ug + ud -2*u[i]
    end
    return du
end

```

taking the jacobian of this function apply to `u = rand(1000)` using multiple backends listed here

```julia
bcks = [
    AutoEnzyme(mode=Enzyme.Reverse),
    AutoEnzyme(mode=Enzyme.Forward),
    AutoMooncake(config=nothing),
    AutoForwardDiff(),
    AutoSparse(
        AutoForwardDiff();
        sparsity_detector=TracerSparsityDetector(),
        coloring_algorithm=GreedyColoringAlgorithm(),
    ),
    AutoSparse(
        AutoEnzyme(mode=Enzyme.Forward);
        sparsity_detector=TracerSparsityDetector(),
        coloring_algorithm=GreedyColoringAlgorithm(),
    )
    ]

```

leads to,

```julia
   1 │ AutoSparse(dense_ad=AutoEnzyme(m… 7.6e-6
   2 │ AutoSparse(dense_ad=AutoForwardD… 1.09e-5
   3 │ AutoEnzyme(mode=ForwardMode{fals… 0.003748
   4 │ AutoForwardDiff() 0.0040038
   5 │ AutoEnzyme(mode=ReverseMode{fals… 0.106355
   6 │ AutoMooncake{Nothing}(nothing) 1.20643

```

The sparsity detection is incredible—I’m excited to see what others will achieve with it! Also, the last two examples use reverse differentiation, which isn’t particularly well-suited for this case.

---

<div class="post-metadata">

### Author: ![yolhan\_mannes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yolhan_mannes/32/220485_2.png) [@yolhan\_mannes](https://discourse.julialang.org/u/yolhan_mannes)
#### Post date: [December 16, 2024, 2:07pm UTC](https://discourse.julialang.org/t/benchmark-autodiff-on-simple-1d-diffusion-operator/123885/2 "2024-12-16T14:07:12Z")

</div>

oh and the full code

```julia
using DifferentiationInterface
using DifferentiationInterfaceTest
using DataFrames
using LinearAlgebra
using SparseConnectivityTracer: TracerSparsityDetector
using SparseMatrixColorings
import Enzyme,ForwardDiff,Mooncake

bcks = [
    AutoEnzyme(mode=Enzyme.Reverse),
    AutoEnzyme(mode=Enzyme.Forward),
    AutoMooncake(config=nothing),
    AutoForwardDiff(),
    AutoSparse(
        AutoForwardDiff();
        sparsity_detector=TracerSparsityDetector(),
        coloring_algorithm=GreedyColoringAlgorithm(),
    ),
    AutoSparse(
        AutoEnzyme(mode=Enzyme.Forward);
        sparsity_detector=TracerSparsityDetector(),
        coloring_algorithm=GreedyColoringAlgorithm(),
    )
    ]

uin() = 0.0
uout() = 0.0
function Diffusion(u)
    du = zero(u)
    for i in eachindex(du,u)
        if i == 1
            ug = uin()
            ud = u[i+1]
        elseif i == length(u)
            ug = u[i-1]
            ud = uout()
        else
            ug = u[i-1]
            ud = u[i+1] 
        end
        du[i] = ug + ud -2*u[i]
    end
    return du
end
function DDiffusion(u)
    A = diagm(
        -1 => ones(length(u)-1),
        0=>-2 .*ones(length(u)),
        1 => ones(length(u)-1))
    return A
end

u = rand(1000)

scenarios = [ 
    Scenario{:jacobian,:out}(Diffusion,u,res1=DDiffusion(u))
    ]
df = benchmark_differentiation(bcks, scenarios)

(df[!,[:backend,:operator,:time]] |> df->filter(df->df.operator == :jacobian,df) |> df-> sort(df,order(:time)))[!,[:backend,:time]]

```

---

<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: [December 16, 2024, 4:40pm UTC](https://discourse.julialang.org/t/benchmark-autodiff-on-simple-1d-diffusion-operator/123885/3 "2024-12-16T16:40:03Z")

</div>

PR this to the SciMLBenchmarks? If you just add a .jmd here

> **[SciMLBenchmarks.jl/benchmarks/AutomaticDifferentiationSparse at master ·...](https://github.com/SciML/SciMLBenchmarks.jl/tree/master/benchmarks/AutomaticDifferentiationSparse)**
>
> Scientific machine learning (SciML) benchmarks, AI for science, and (differential) equation solvers. Covers Julia, Python (PyTorch, Jax), MATLAB, R - SciML/SciMLBenchmarks.jl

it will automatically make the page and we will keep this updating. It is nice to have a simple case like this.

---

<div class="post-metadata">

### Author: ![yolhan\_mannes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yolhan_mannes/32/220485_2.png) [@yolhan\_mannes](https://discourse.julialang.org/u/yolhan_mannes)
#### Post date: [December 16, 2024, 5:24pm UTC](https://discourse.julialang.org/t/benchmark-autodiff-on-simple-1d-diffusion-operator/123885/4 "2024-12-16T17:24:21Z")

</div>

Done thank you for the advice.  
Even thought, I’ve used julia for a while, it is my first PR ever, I hope I did everything right.
