Diffusion operator loop sparse AD benchmarks

using DifferentiationInterface
using DifferentiationInterfaceTest
using Chairmarks, DataFrames
using LinearAlgebra
using SparseConnectivityTracer: TracerSparsityDetector
using SparseMatrixColorings
import Chairmarks
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()
 ADTypes.AutoForwardDiff()
 ADTypes.AutoSparse(dense_ad=ADTypes.AutoForwardDiff(), sparsity_detector=S
parseConnectivityTracer.TracerSparsityDetector(), coloring_algorithm=Sparse
MatrixColorings.GreedyColoringAlgorithm{:direct, 1, Tuple{SparseMatrixColor
ings.NaturalOrder}}((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, 1, Tuple{SparseMatrixColorings
.NaturalOrder}}((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 = DataFrame(benchmark_differentiation(bcks, scenarios))
table = PrettyTables.pretty_table(
    String,
    df;
    backend = :markdown,
    column_labels = names(df),
    formatters = [PrettyTables.fmt__printf("%.1e")],
)

Markdown.parse(table)
Test Summary:                                                              
                                                                           
                                                                           
                                                                           
                                                                  | Pass  T
otal     Time
Testing benchmarks                                                         
                                                                           
                                                                           
                                                                           
                                                                  |   12   
  12  1m52.3s
  ADTypes.AutoEnzyme(mode=EnzymeCore.ReverseMode{false, false, false, Enzym
eCore.FFIABI, false, false}())                                             
                                                                           
                                                                           
                                                                  |    2   
   2    28.8s
  ADTypes.AutoEnzyme(mode=EnzymeCore.ForwardMode{false, EnzymeCore.FFIABI, 
false, false, false}())                                                    
                                                                           
                                                                           
                                                                  |    2   
   2    30.6s
  ADTypes.AutoMooncake()                                                   
                                                                           
                                                                           
                                                                           
                                                                  |    2   
   2    40.7s
  ADTypes.AutoForwardDiff()                                                
                                                                           
                                                                           
                                                                           
                                                                  |    2   
   2     4.4s
  ADTypes.AutoSparse(dense_ad=ADTypes.AutoForwardDiff(), sparsity_detector=
SparseConnectivityTracer.TracerSparsityDetector(), coloring_algorithm=Spars
eMatrixColorings.GreedyColoringAlgorithm{:direct, 1, Tuple{SparseMatrixColo
rings.NaturalOrder}}((SparseMatrixColorings.NaturalOrder(),), false))      
                                                                  |    2   
   2     4.2s
  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, 1, Tuple{SparseMatrixColoring
s.NaturalOrder}}((SparseMatrixColorings.NaturalOrder(),), false)) |    2   
   2     3.3s
backendscenariooperatorpreparedcallssamplesevalstimeallocsbytesgc_fractioncompile_fraction
AutoEnzyme(mode=ReverseMode{false, false, false, FFIABI, false, false}())Scenario{:jacobian,:out} Diffusion : Vector{Float64} -> Vector{Float64}valueandjacobian1.0e+006.4e+019.0e+001.0e+001.1e-012.3e+032.8e+083.1e-020.0e+00
AutoEnzyme(mode=ReverseMode{false, false, false, FFIABI, false, false}())Scenario{:jacobian,:out} Diffusion : Vector{Float64} -> Vector{Float64}jacobian1.0e+006.3e+019.0e+001.0e+001.0e-012.3e+032.8e+081.5e-020.0e+00
AutoEnzyme(mode=ForwardMode{false, FFIABI, false, false, false}())Scenario{:jacobian,:out} Diffusion : Vector{Float64} -> Vector{Float64}valueandjacobian1.0e+006.3e+018.7e+011.0e+007.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+011.0e+021.0e+007.8e-033.2e+031.8e+070.0e+000.0e+00
AutoMooncake()Scenario{:jacobian,:out} Diffusion : Vector{Float64} -> Vector{Float64}valueandjacobian1.0e+001.0e+001.9e+011.0e+004.9e-027.0e+033.3e+070.0e+000.0e+00
AutoMooncake()Scenario{:jacobian,:out} Diffusion : Vector{Float64} -> Vector{Float64}jacobian1.0e+000.0e+002.0e+011.0e+004.9e-027.0e+033.3e+070.0e+000.0e+00
AutoForwardDiff()Scenario{:jacobian,:out} Diffusion : Vector{Float64} -> Vector{Float64}valueandjacobian1.0e+008.5e+011.7e+021.0e+005.0e-031.7e+021.7e+070.0e+000.0e+00
AutoForwardDiff()Scenario{:jacobian,:out} Diffusion : Vector{Float64} -> Vector{Float64}jacobian1.0e+008.4e+011.8e+021.0e+005.0e-031.7e+021.7e+070.0e+000.0e+00
AutoSparse(densead=AutoForwardDiff(), sparsitydetector=TracerSparsityDetector(), coloring_algorithm=GreedyColoringAlgorithm{:direct, 1, Tuple{NaturalOrder}}((NaturalOrder(),), false))Scenario{:jacobian,:out} Diffusion : Vector{Float64} -> Vector{Float64}valueandjacobian1.0e+002.0e+003.5e+041.0e+001.9e-058.0e+009.6e+040.0e+000.0e+00
AutoSparse(densead=AutoForwardDiff(), sparsitydetector=TracerSparsityDetector(), coloring_algorithm=GreedyColoringAlgorithm{:direct, 1, Tuple{NaturalOrder}}((NaturalOrder(),), false))Scenario{:jacobian,:out} Diffusion : Vector{Float64} -> Vector{Float64}jacobian1.0e+001.0e+004.0e+041.0e+001.6e-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, 1, Tuple{NaturalOrder}}((NaturalOrder(),), false))Scenario{:jacobian,:out} Diffusion : Vector{Float64} -> Vector{Float64}valueandjacobian1.0e+002.0e+004.0e+041.0e+001.4e-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, 1, Tuple{NaturalOrder}}((NaturalOrder(),), false))Scenario{:jacobian,:out} Diffusion : Vector{Float64} -> Vector{Float64}jacobian1.0e+001.0e+004.6e+041.0e+001.3e-059.0e+008.9e+040.0e+000.0e+00