Diffusion operator loop sparse AD benchmarks

using DifferentiationInterface
using DifferentiationInterfaceTest
using LinearAlgebra
using SparseConnectivityTracer: TracerSparsityDetector
using SparseMatrixColorings
import Enzyme, ForwardDiff, Mooncake
import Markdown, PrettyTables, Printf

Backends tested

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()
    )
]
6-element Vector{ADTypes.AbstractADType}:
 ADTypes.AutoEnzyme(mode=EnzymeCore.ReverseMode{false, false, false, Enzyme
Core.FFIABI, false, false}())
 ADTypes.AutoEnzyme(mode=EnzymeCore.ForwardMode{false, EnzymeCore.FFIABI, f
alse, false, false}())
 ADTypes.AutoMooncake{Nothing}(nothing)
 ADTypes.AutoForwardDiff()
 ADTypes.AutoSparse(dense_ad=ADTypes.AutoForwardDiff(), sparsity_detector=S
parseConnectivityTracer.TracerSparsityDetector(), coloring_algorithm=Sparse
MatrixColorings.GreedyColoringAlgorithm{:direct, SparseMatrixColorings.Natu
ralOrder}(SparseMatrixColorings.NaturalOrder(), false))
 ADTypes.AutoSparse(dense_ad=ADTypes.AutoEnzyme(mode=EnzymeCore.ForwardMode
{false, EnzymeCore.FFIABI, false, false, false}()), sparsity_detector=Spars
eConnectivityTracer.TracerSparsityDetector(), coloring_algorithm=SparseMatr
ixColorings.GreedyColoringAlgorithm{:direct, SparseMatrixColorings.NaturalO
rder}(SparseMatrixColorings.NaturalOrder(), false))

Diffusion operator simple loop

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;

Manual jacobian

function DDiffusion(u)
    A = diagm(
        -1 => ones(length(u)-1),
        0=>-2 .* ones(length(u)),
        1 => ones(length(u)-1))
    return A
end;

Define Scenarios

u = rand(1000)
scenarios = [Scenario{:jacobian, :out}(Diffusion, u, res1 = DDiffusion(u))];

Run Benchmarks

df = benchmark_differentiation(bcks, scenarios)
table = PrettyTables.pretty_table(
    String,
    df;
    backend = Val(:markdown),
    header = names(df),
    formatters = PrettyTables.ft_printf("%.1e")
)

Markdown.parse(table)
Test Summary:                                                              
                                                                           
                                                                           
                                                                           
                                                     | Pass  Total     Time
Testing benchmarks                                                         
                                                                           
                                                                           
                                                                           
                                                     |   12     12  2m24.9s
  ADTypes.AutoEnzyme(mode=EnzymeCore.ReverseMode{false, false, false, Enzym
eCore.FFIABI, false, false}())                                             
                                                                           
                                                                           
                                                     |    2      2    37.7s
  ADTypes.AutoEnzyme(mode=EnzymeCore.ForwardMode{false, EnzymeCore.FFIABI, 
false, false, false}())                                                    
                                                                           
                                                                           
                                                     |    2      2    37.5s
  ADTypes.AutoMooncake{Nothing}(nothing)                                   
                                                                           
                                                                           
                                                                           
                                                     |    2      2    55.5s
  ADTypes.AutoForwardDiff()                                                
                                                                           
                                                                           
                                                                           
                                                     |    2      2     4.9s
  ADTypes.AutoSparse(dense_ad=ADTypes.AutoForwardDiff(), sparsity_detector=
SparseConnectivityTracer.TracerSparsityDetector(), coloring_algorithm=Spars
eMatrixColorings.GreedyColoringAlgorithm{:direct, SparseMatrixColorings.Nat
uralOrder}(SparseMatrixColorings.NaturalOrder(), false))                   
                                                     |    2      2     4.9s
  ADTypes.AutoSparse(dense_ad=ADTypes.AutoEnzyme(mode=EnzymeCore.ForwardMod
e{false, EnzymeCore.FFIABI, false, false, false}()), sparsity_detector=Spar
seConnectivityTracer.TracerSparsityDetector(), coloring_algorithm=SparseMat
rixColorings.GreedyColoringAlgorithm{:direct, SparseMatrixColorings.Natural
Order}(SparseMatrixColorings.NaturalOrder(), false)) |    2      2     4.0s
backendscenariooperatorpreparedcallssamplesevalstimeallocsbytesgc_fractioncompile_fraction
AutoEnzyme(mode=ReverseMode{false, false, false, FFIABI, false, false}())Scenario{:jacobian,:out} Diffusion : Vector{Float64} -> Vector{Float64}valueandjacobian1.0e+006.4e+017.0e+001.0e+001.3e-012.3e+032.8e+086.9e-020.0e+00
AutoEnzyme(mode=ReverseMode{false, false, false, FFIABI, false, false}())Scenario{:jacobian,:out} Diffusion : Vector{Float64} -> Vector{Float64}jacobian1.0e+006.3e+018.0e+001.0e+001.3e-012.3e+032.8e+086.9e-020.0e+00
AutoEnzyme(mode=ForwardMode{false, FFIABI, false, false, false}())Scenario{:jacobian,:out} Diffusion : Vector{Float64} -> Vector{Float64}valueandjacobian1.0e+006.3e+016.9e+011.0e+008.5e-033.2e+031.8e+070.0e+000.0e+00
AutoEnzyme(mode=ForwardMode{false, FFIABI, false, false, false}())Scenario{:jacobian,:out} Diffusion : Vector{Float64} -> Vector{Float64}jacobian1.0e+006.3e+017.6e+011.0e+008.6e-033.2e+031.8e+070.0e+000.0e+00
AutoMooncake{Nothing}(nothing)Scenario{:jacobian,:out} Diffusion : Vector{Float64} -> Vector{Float64}valueandjacobian1.0e+001.0e+001.0e+001.0e+001.1e+001.2e+044.0e+091.5e-010.0e+00
AutoMooncake{Nothing}(nothing)Scenario{:jacobian,:out} Diffusion : Vector{Float64} -> Vector{Float64}jacobian1.0e+000.0e+001.0e+001.0e+001.1e+001.2e+044.0e+091.5e-010.0e+00
AutoForwardDiff()Scenario{:jacobian,:out} Diffusion : Vector{Float64} -> Vector{Float64}valueandjacobian1.0e+008.5e+011.4e+021.0e+005.5e-031.7e+021.7e+070.0e+000.0e+00
AutoForwardDiff()Scenario{:jacobian,:out} Diffusion : Vector{Float64} -> Vector{Float64}jacobian1.0e+008.4e+011.5e+021.0e+005.5e-031.7e+021.7e+070.0e+000.0e+00
AutoSparse(densead=AutoForwardDiff(), sparsitydetector=TracerSparsityDetector(), coloring_algorithm=GreedyColoringAlgorithm{:direct, NaturalOrder}(NaturalOrder(), false))Scenario{:jacobian,:out} Diffusion : Vector{Float64} -> Vector{Float64}valueandjacobian1.0e+002.0e+002.0e+041.0e+002.1e-058.0e+009.6e+040.0e+000.0e+00
AutoSparse(densead=AutoForwardDiff(), sparsitydetector=TracerSparsityDetector(), coloring_algorithm=GreedyColoringAlgorithm{:direct, NaturalOrder}(NaturalOrder(), false))Scenario{:jacobian,:out} Diffusion : Vector{Float64} -> Vector{Float64}jacobian1.0e+001.0e+002.3e+041.0e+001.8e-057.0e+008.8e+040.0e+000.0e+00
AutoSparse(densead=AutoEnzyme(mode=ForwardMode{false, FFIABI, false, false, false}()), sparsitydetector=TracerSparsityDetector(), coloring_algorithm=GreedyColoringAlgorithm{:direct, NaturalOrder}(NaturalOrder(), false))Scenario{:jacobian,:out} Diffusion : Vector{Float64} -> Vector{Float64}valueandjacobian1.0e+002.0e+002.3e+041.0e+001.8e-051.0e+019.7e+040.0e+000.0e+00
AutoSparse(densead=AutoEnzyme(mode=ForwardMode{false, FFIABI, false, false, false}()), sparsitydetector=TracerSparsityDetector(), coloring_algorithm=GreedyColoringAlgorithm{:direct, NaturalOrder}(NaturalOrder(), false))Scenario{:jacobian,:out} Diffusion : Vector{Float64} -> Vector{Float64}jacobian1.0e+001.0e+002.5e+041.0e+001.4e-059.0e+008.9e+040.0e+000.0e+00