Diffusion operator loop sparse AD benchmarks

using DifferentiationInterface
using DifferentiationInterfaceTest
using Chairmarks
using 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  2m32.7s
  ADTypes.AutoEnzyme(mode=EnzymeCore.ReverseMode{false, false, false, Enzym
eCore.FFIABI, false, false}())                                             
                                                                           
                                                                           
                                                                  |    2   
   2    46.5s
  ADTypes.AutoEnzyme(mode=EnzymeCore.ForwardMode{false, EnzymeCore.FFIABI, 
false, false, false}())                                                    
                                                                           
                                                                           
                                                                  |    2   
   2    50.8s
  ADTypes.AutoMooncake()                                                   
                                                                           
                                                                           
                                                                           
                                                                  |    2   
   2    42.6s
  ADTypes.AutoForwardDiff()                                                
                                                                           
                                                                           
                                                                           
                                                                  |    2   
   2     4.1s
  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.5s
  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.8s
backendscenariooperatorpreparedcallssamplesevalstimeallocsbytesgc_fractioncompile_fraction
AutoEnzyme(mode=ReverseMode{false, false, false, FFIABI, false, false}())Scenario{:jacobian,:out} Diffusion : Vector{Float64} -\> Vector{Float64}valueandjacobian1.0e+006.4e+016.0e+001.0e+001.1e-016.6e+032.8e+083.1e-010.0e+00
AutoEnzyme(mode=ReverseMode{false, false, false, FFIABI, false, false}())Scenario{:jacobian,:out} Diffusion : Vector{Float64} -\> Vector{Float64}jacobian1.0e+006.3e+017.0e+001.0e+008.9e-026.6e+032.8e+082.0e-010.0e+00
AutoEnzyme(mode=ForwardMode{false, FFIABI, false, false, false}())Scenario{:jacobian,:out} Diffusion : Vector{Float64} -\> Vector{Float64}valueandjacobian1.0e+006.3e+014.4e+011.0e+004.6e-035.3e+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+016.3e+011.0e+004.6e-035.3e+031.8e+070.0e+000.0e+00
AutoMooncake()Scenario{:jacobian,:out} Diffusion : Vector{Float64} -\> Vector{Float64}valueandjacobian1.0e+001.0e+001.4e+011.0e+005.2e-021.1e+043.3e+070.0e+000.0e+00
AutoMooncake()Scenario{:jacobian,:out} Diffusion : Vector{Float64} -\> Vector{Float64}jacobian1.0e+000.0e+001.3e+011.0e+005.2e-021.1e+043.3e+070.0e+000.0e+00
AutoForwardDiff()Scenario{:jacobian,:out} Diffusion : Vector{Float64} -\> Vector{Float64}valueandjacobian1.0e+008.5e+019.2e+011.0e+003.0e-032.6e+021.7e+070.0e+000.0e+00
AutoForwardDiff()Scenario{:jacobian,:out} Diffusion : Vector{Float64} -\> Vector{Float64}jacobian1.0e+008.4e+011.1e+021.0e+003.0e-032.6e+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+002.2e+041.0e+001.5e-051.5e+019.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+002.5e+041.0e+001.4e-051.2e+018.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+001.7e+041.0e+001.6e-052.3e+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+001.9e+041.0e+001.1e-052.0e+018.9e+040.0e+000.0e+00