Backends

DifferentiationInterface.jl is based on two concepts: operators and backends. This page is about the latter, check out that page to learn about the former.

List of backends

We support all dense backend choices from ADTypes.jl, as well as their sparse wrapper AutoSparse.

BackendAvailabilityTwo-argument functionsHessian supportExample
Diffractor (forward/reverse)AutoDiffractor()
Enzyme (forward)AutoEnzyme(; mode=Enzyme.Forward)
Enzyme (reverse)AutoEnzyme(; mode=Enzyme.Reverse)
FastDifferentiation (symbolic)AutoFastDifferentiation()
FiniteDiff (forward)AutoFiniteDiff()
FiniteDifferences (forward)AutoFiniteDifferences(; fdm=FiniteDifferences.central_fdm(3, 1))
ForwardDiff (forward)AutoForwardDiff()
PolyesterForwardDiff (forward)AutoPolyesterForwardDiff(; chunksize=1)
ReverseDiff (reverse)AutoReverseDiff()
Symbolics (symbolic)AutoSymbolics()
Tapir (reverse)AutoTapir(; safe_mode=false)
Tracker (reverse)AutoTracker()
Zygote (reverse)AutoZygote()
Compatibility with Julia 1.6

As of version 0.3.4, DifferentiationInterface.jl is compatible with Julia 1.6, the Long Term Support (LTS) version of the language. However, we were only able to test the following backends on LTS:

  • FiniteDifferences.jl
  • ForwardDiff.jl
  • ReverseDiff.jl
  • Tracker.jl
  • Zygote.jl

We strongly recommend that users upgrade to Julia 1.10, where all backends are tested.

Checks

Availability

You can use check_available to verify whether a given backend is loaded.

Support for two-argument functions

All backends are compatible with one-argument functions f(x) = y. Only some are compatible with two-argument functions f!(y, x) = nothing. You can use check_twoarg to verify this compatibility.

Support for Hessian

Only some backends are able to compute Hessians. You can use check_hessian to verify this feature (beware that it will try to compute a small Hessian, so it is not instantaneous like the other checks).

Backend switch

The wrapper DifferentiateWith allows you to switch between backends. It takes a function f and specifies that f should be differentiated with the backend of your choice, instead of whatever other backend the code is trying to use. In other words, when someone tries to differentiate dw = DifferentiateWith(f, backend1) with backend2, then backend1 steps in and backend2 does nothing. At the moment, DifferentiateWith only works when backend2 supports ChainRules.jl.

Defining your own

To work with DifferentiationInterface.jl, a new AD system would need to create an object subtyping ADTypes.AbstractADType. In addition, some low-level operators would need to be defined at the very least:

backend subtypepushforward necessarypullback necessary
ADTypes.ForwardModeyesno
ADTypes.ReverseModenoyes
ADTypes.SymbolicModeyesyes

Every backend we support corresponds to a package extension of DifferentiationInterface.jl (located in the ext subfolder). If you need to implement your own backend, take a look in there for inspiration, or reach out to us in the GitHub issues.