Skip to content

Commit

Permalink
Add CONTRIBUTING and restructure dev guide
Browse files Browse the repository at this point in the history
  • Loading branch information
gdalle committed Jul 30, 2024
1 parent 4fd9733 commit bc66b05
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 77 deletions.
12 changes: 12 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Contributing

Thank you for wanting to contribute to [DifferentiationInterface.jl](https://github.com/gdalle/DifferentiationInterface.jl)!
If you have a potential improvement in mind, please [open an issue](https://github.com/gdalle/DifferentiationInterface.jl/issues/new/choose) first to discuss it with the maintainers.
Don't hesitate to ping said maintainers ([`@gdalle`](https://github.com/gdalle) and [`@adrhill`](https://github.com/adrhill)) if they don't answer within a week or so.
Once your issue receives positive feedback, you're welcome to open a pull request.

The repository follows the [ColPrac](https://github.com/SciML/ColPrac) best practices, and its code is formatted using [BlueStyle](https://github.com/JuliaDiff/BlueStyle).
Please refer to the [dev guide](https://gdalle.github.io/DifferentiationInterface.jl/DifferentiationInterface/stable/dev_guide/) for details on the package structure and the testing pipeline.

By default, CI only runs tests on the latest stable release of Julia.
Before merging any PR, it must be given the label `fulltest` so that more Julia versions are tested (LTS and pre-release).
2 changes: 1 addition & 1 deletion DifferentiationInterface/docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ makedocs(;
"Home" => "index.md",
"Tutorials" => ["tutorial1.md", "tutorial2.md"],
"Reference" => ["operators.md", "backends.md", "api.md"],
"Advanced" => ["dev_guide.md", "overloads.md"],
"Advanced" => ["dev_guide.md", "implementations.md"],
],
plugins=[links],
)
Expand Down
66 changes: 6 additions & 60 deletions DifferentiationInterface/docs/src/dev_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ The package is structured around 8 [operators](@ref Operators):

Most operators have 4 variants, which look like this in the first order: `operator`, `operator!`, `value_and_operator`, `value_and_operator!`.

### New operator
## New operator

To implement a new operator for an existing backend, you need to write 5 methods: 1 for [preparation](@ref Preparation) and 4 corresponding to the variants of the operator (see above).
In some cases, a subset of those methods will be enough, but most of the time, forgetting one will trigger errors.
Expand All @@ -32,12 +32,12 @@ For instance, `prepare_gradient(f, backend, x)` must return a [`DifferentiationI
Assuming you don't need any preparation for said operator, you can use the trivial extras that are already defined, like `DifferentiationInterface.NoGradientExtras`.
Otherwise, define a custom struct like `MyGradientExtras <: DifferentiationInterface.GradientExtras` and put the necessary storage in there.

### New backend
## New backend

If you want to implement a new backend, for instance because you developed a new AD package called `SuperDiff`, please open a pull request to DifferentiationInterface.jl.
Your AD package needs to be registered first.

#### Core code
### Core code

In the main package, you should define a new struct `SuperDiffBackend` which subtypes [`ADTypes.AbstractADType`](@extref ADTypes), and endow it with the fields you need to parametrize your differentiation routines.
You also have to define [`ADTypes.mode`](@extref) and [`DifferentiationInterface.twoarg_support`](@ref) on `SuperDiffBackend`.
Expand All @@ -58,10 +58,10 @@ The exact requirements depend on the differentiation mode you chose:

Every other operator can be deduced from these two, but you can gain efficiency by implementing additional operators.

#### Tests and docs
### Tests and docs

Once that is done, you need to add your new backend to the test suite.
Test files should be gathered in a folder named `SuperDiff` inside [`DifferentiationInterface/test/Single`](https://github.com/gdalle/DifferentiationInterface.jl/tree/main/DifferentiationInterface/test/Single).
Test files should be gathered in a folder named `SuperDiff` inside [`DifferentiationInterface/test/Back`](https://github.com/gdalle/DifferentiationInterface.jl/tree/main/DifferentiationInterface/test/Back).
They should use [DifferentiationInterfaceTest.jl](https://github.com/gdalle/DifferentiationInterface.jl/tree/main/DifferentiationInterfaceTest) to check correctness against the default scenarios.
Take inspiration from the tests of other backends to write your own.
To activate tests in CI, modify the [test workflow](https://github.com/gdalle/DifferentiationInterface.jl/blob/main/.github/workflows/Test.yml) and add your package to the list.
Expand All @@ -74,64 +74,10 @@ GROUP = get(ENV, "JULIA_DI_TEST_GROUP", "All")
with the much cheaper version

```julia
GROUP = get(ENV, "JULIA_DI_TEST_GROUP", "Single/SuperDiff")
GROUP = get(ENV, "JULIA_DI_TEST_GROUP", "Back/SuperDiff")
```

but don't forget to switch it back before pushing.

Finally, you need to add your backend to the documentation, modifying every page that involves a list of backends.
That includes the README.

## Specific details

Here we give some more information on the contents of the extension for each backend.

### ChainRulesCore

For [`pullback`](@ref), same-point preparation runs the forward sweep and returns the pullback closure.

### Enzyme

In forward mode, for [`gradient`](@ref) and [`jacobian`](@ref), preparation chooses a number of chunks.

### FastDifferentiation

Preparation generates an [executable function](https://brianguenter.github.io/FastDifferentiation.jl/stable/makefunction/) from the symbolic expression of the differentiated function.

!!! warning
Preparation can be very slow for symbolic AD.

### FiniteDiff

Whenever possible, preparation creates a cache object.

### ForwardDiff

Wherever possible, preparation creates a [config](https://juliadiff.org/ForwardDiff.jl/stable/user/api/#Preallocating/Configuring-Work-Buffers).
For [`pushforward`](@ref), preparation allocates the necessary space for `Dual` number computations.

### ReverseDiff

Wherever possible, preparation records a [tape](https://juliadiff.org/ReverseDiff.jl/dev/api/#The-AbstractTape-API) of the function's execution.

!!! warning
This tape is specific to the control flow inside the function, and cannot be reused if the control flow is value-dependent (like `if x[1] > 0`).

### Symbolics

Preparation generates an [executable function](https://docs.sciml.ai/Symbolics/stable/manual/build_function/) from the symbolic expression of the differentiated function.

!!! warning
Preparation can be very slow for symbolic AD.

### Tapir

For [`pullback`](@ref), preparation [builds the reverse rule](https://github.com/withbayes/Tapir.jl?tab=readme-ov-file#how-it-works) of the function.

### Tracker

For [`pullback`](@ref), same-point preparation runs the forward sweep and returns the pullback closure at `x`.

### Zygote

For [`pullback`](@ref), same-point preparation runs the forward sweep and returns the pullback closure at `x`.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Overloads
# Implementations

DifferentiationInterface.jl provides a handful of [operators](@ref "Operators") like [`gradient`](@ref) or [`jacobian`](@ref), each with several variants:

Expand All @@ -7,9 +7,11 @@ DifferentiationInterface.jl provides a handful of [operators](@ref "Operators")
- support for **one-argument functions** `y = f(x)` or **two-argument functions** `f!(y, x)`

While it is possible to define every operator using just [`pushforward`](@ref) and [`pullback`](@ref), some backends have more efficient implementations of high-level operators.
When they are available, we **always** call these backend-specific overloads.
When they are available, we nearly always call these backend-specific overloads.
We also adapt the preparation phase accordingly.
This page gives details on each backend's bindings.

The following tables summarize all implemented overloads for each backend.
The tables below summarize all implemented overloads for each backend.
The cells can have three values:

- ❌: the operator is not overloaded because the backend does not support it
Expand Down Expand Up @@ -166,79 +168,113 @@ function print_overloads(backend, ext::Symbol)
end
```

## Diffractor (forward/reverse)
## ChainRulesCore

For [`pullback`](@ref), same-point preparation runs the forward sweep and returns the pullback closure.

## Diffractor

```@example overloads
print_overloads(AutoDiffractor(), :DifferentiationInterfaceDiffractorExt) # hide
```

## Enzyme (forward)
## Enzyme

### Forward mode

In forward mode, for [`gradient`](@ref) and [`jacobian`](@ref), preparation chooses a number of chunks.

```@example overloads
print_overloads(AutoEnzyme(; mode=Enzyme.Forward), :DifferentiationInterfaceEnzymeExt) # hide
```

## Enzyme (reverse)
### Reverse mode

```@example overloads
print_overloads(AutoEnzyme(; mode=Enzyme.Reverse), :DifferentiationInterfaceEnzymeExt) # hide
```

## FastDifferentiation (symbolic)
## FastDifferentiation

Preparation generates an [executable function](https://brianguenter.github.io/FastDifferentiation.jl/stable/makefunction/) from the symbolic expression of the differentiated function.

!!! warning
Preparation can be very slow for symbolic AD.

```@example overloads
print_overloads(AutoFastDifferentiation(), :DifferentiationInterfaceFastDifferentiationExt) # hide
```

## FiniteDiff (forward)
## FiniteDiff

Whenever possible, preparation creates a cache object.

```@example overloads
print_overloads(AutoFiniteDiff(), :DifferentiationInterfaceFiniteDiffExt) # hide
```

## FiniteDifferences (forward)
## FiniteDifferences

```@example overloads
print_overloads(AutoFiniteDifferences(; fdm=FiniteDifferences.central_fdm(3, 1)), :DifferentiationInterfaceFiniteDifferencesExt) # hide
```

## ForwardDiff (forward)
## ForwardDiff

Wherever possible, preparation creates a [config](https://juliadiff.org/ForwardDiff.jl/stable/user/api/#Preallocating/Configuring-Work-Buffers).
For [`pushforward`](@ref), preparation allocates the necessary space for `Dual` number computations.

```@example overloads
print_overloads(AutoForwardDiff(), :DifferentiationInterfaceForwardDiffExt) # hide
```

## PolyesterForwardDiff (forward)
## PolyesterForwardDiff

```@example overloads
print_overloads(AutoPolyesterForwardDiff(; chunksize=1), :DifferentiationInterfacePolyesterForwardDiffExt) # hide
```

## ReverseDiff (reverse)
## ReverseDiff

Wherever possible, preparation records a [tape](https://juliadiff.org/ReverseDiff.jl/dev/api/#The-AbstractTape-API) of the function's execution.

!!! warning
This tape is specific to the control flow inside the function, and cannot be reused if the control flow is value-dependent (like `if x[1] > 0`).

```@example overloads
print_overloads(AutoReverseDiff(), :DifferentiationInterfaceReverseDiffExt) # hide
```

## Symbolics (symbolic)
## Symbolics

Preparation generates an [executable function](https://docs.sciml.ai/Symbolics/stable/manual/build_function/) from the symbolic expression of the differentiated function.

!!! warning
Preparation can be very slow for symbolic AD.

```@example overloads
print_overloads(AutoSymbolics(), :DifferentiationInterfaceSymbolicsExt) # hide
```

## Tapir (reverse)
## Tapir

For [`pullback`](@ref), preparation [builds the reverse rule](https://github.com/withbayes/Tapir.jl?tab=readme-ov-file#how-it-works) of the function.

```@example overloads
print_overloads(AutoTapir(), :DifferentiationInterfaceTapirExt) # hide
```

## Tracker (reverse)
## Tracker

For [`pullback`](@ref), same-point preparation runs the forward sweep and returns the pullback closure at `x`.

```@example overloads
print_overloads(AutoTracker(), :DifferentiationInterfaceTrackerExt) # hide
```

## Zygote (reverse)
## Zygote

For [`pullback`](@ref), same-point preparation runs the forward sweep and returns the pullback closure at `x`.

```@example overloads
print_overloads(AutoZygote(), :DifferentiationInterfaceZygoteExt) # hide
Expand Down

0 comments on commit bc66b05

Please sign in to comment.