-
Notifications
You must be signed in to change notification settings - Fork 82
Add DI integration tests #2531
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add DI integration tests #2531
Changes from 18 commits
8b40794
04753f7
386b24a
d701f1c
155db97
b13351d
848ca79
06d6bb3
340094f
b7500d4
f99f773
2610553
3f1ea02
9abe469
8b01fbf
43783e0
295e5f9
2351333
f67994d
dea135c
e23c4d3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| name: Integration | ||
| on: | ||
| pull_request: | ||
| push: | ||
| branches: | ||
| - main | ||
| - release-* | ||
| tags: '*' | ||
wsmoses marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| concurrency: | ||
| # Skip intermediate builds: always. | ||
| # Cancel intermediate builds: only if it is a pull request build. | ||
| group: ${{ github.workflow }}-${{ github.ref }} | ||
| cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} | ||
|
|
||
| jobs: | ||
| integration: | ||
| timeout-minutes: 45 | ||
| name: Integration Tests - ${{ matrix.package }} - Julia ${{ matrix.version }} | ||
| runs-on: ${{ matrix.os }} | ||
| container: | ||
| image: ${{ (contains(matrix.os, 'linux') && 'ghcr.io/enzymead/reactant-docker-images@sha256:91e1edb7a7c869d5a70db06e417f22907be0e67ca86641d48adcea221fedc674' ) || '' }} | ||
| env: | ||
| JULIA_PKG_SERVER_REGISTRY_PREFERENCE: eager | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| version: | ||
| - '1.10' | ||
giordano marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| - '1.11' | ||
| os: | ||
| - linux-x86-n2-32 | ||
| package: | ||
| - Bijectors | ||
| - DifferentiationInterface | ||
| - DynamicExpressions | ||
| steps: | ||
| - uses: actions/checkout@v5 | ||
| - uses: julia-actions/setup-julia@v2 | ||
| with: | ||
| version: ${{ matrix.version }} | ||
| - uses: julia-actions/cache@v2 | ||
| - uses: julia-actions/julia-buildpkg@v1 | ||
| - name: "Install Dependencies" | ||
| run: | | ||
| julia --color=yes --project=test/integration/${{ matrix.package }} --threads=auto --check-bounds=yes -O1 -e 'using Pkg; Pkg.develop([PackageSpec(; path) for path in (".", "lib/EnzymeCore")])' | ||
| shell: bash | ||
| if: ${{ matrix.version == '1.10' }} | ||
| - name: "Instantiate" | ||
| run: | | ||
| julia --color=yes --project=test/integration/${{ matrix.package }} --threads=auto --check-bounds=yes -O1 -e 'using Pkg; Pkg.instantiate()' | ||
| shell: bash | ||
| - name: "Run tests" | ||
| run: | | ||
| julia --color=yes --project=test/integration/${{ matrix.package }} --threads=auto --check-bounds=yes -O1 test/integration/${{ matrix.package }}/runtests.jl | ||
| shell: bash | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -131,7 +131,11 @@ end | |
| sum_b_binv_test_case(Bijectors.VecCholeskyBijector(:U), 3), | ||
| sum_b_binv_test_case(Bijectors.VecCholeskyBijector(:U), 0), | ||
| sum_b_binv_test_case(Bijectors.Coupling(Bijectors.Shift, Bijectors.PartitionMask(3, [1], [2])), 3), | ||
| sum_b_binv_test_case(Bijectors.InvertibleBatchNorm(3), (3, 3)), | ||
| sum_b_binv_test_case( | ||
| Bijectors.InvertibleBatchNorm(3), | ||
| (3, 3), | ||
|
||
| broken = (VERSION >= v"1.11" ? Both : Neither) | ||
| ), | ||
wsmoses marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| sum_b_binv_test_case(Bijectors.LeakyReLU(0.2), 3), | ||
| sum_b_binv_test_case(Bijectors.Logit(0.1, 0.3), 3), | ||
| sum_b_binv_test_case(Bijectors.PDBijector(), (3, 3)), | ||
|
|
@@ -186,6 +190,7 @@ end | |
| end, | ||
| randn(rng, 7); | ||
| name="PlanarLayer7", | ||
| broken = (VERSION >= v"1.11" ? Forward : Neither), | ||
wsmoses marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ), | ||
|
|
||
| TestCase( | ||
|
|
@@ -197,6 +202,7 @@ end | |
| end, | ||
| randn(rng, 11); | ||
| name="PlanarLayer11", | ||
| broken = (VERSION >= v"1.11" ? Forward : Neither), | ||
| ), | ||
| ] | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| [deps] | ||
| ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b" | ||
| DifferentiationInterface = "a0c0ee7d-e4b9-4e03-894e-1c5f64a51d63" | ||
| DifferentiationInterfaceTest = "a82114a7-5aa3-49a8-9643-716bb13727a3" | ||
| Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" | ||
| EnzymeCore = "f151be2c-9106-41f4-ab19-57ee4f262869" | ||
| StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" | ||
| Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" | ||
|
|
||
| [sources] | ||
| Enzyme = { path = "../../.." } | ||
| EnzymeCore = { path = "../../../lib/EnzymeCore" } | ||
|
|
||
| [compat] | ||
| ADTypes = "1.17.0" | ||
| DifferentiationInterface = "=0.7.7" | ||
| DifferentiationInterfaceTest = "=0.10.2" | ||
| StaticArrays = "1.9" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| # DI integration tests for Enzyme | ||
|
|
||
| This folder contains tests to ensure that changes to Enzyme do not break integration with [DifferentiationInterface](https://github.com/JuliaDiff/DifferentiationInterface.jl) (DI). | ||
|
|
||
| ## Relevant source files | ||
|
|
||
| The test utilities used here come from the sibling package [DifferentiationInterfaceTest](https://github.com/JuliaDiff/DifferentiationInterface.jl/tree/main/DifferentiationInterfaceTest) (DIT). | ||
| Correctness checking itself is implemented in [`src/tests/correctness_eval.jl`](https://github.com/JuliaDiff/DifferentiationInterface.jl/blob/ed5655a90bf9f3a6092904070d353a9d705ebdc4/DifferentiationInterfaceTest/src/tests/correctness_eval.jl), which is where you will see test errors originating. | ||
| Test scenarios are located in [`src/scenarios`](https://github.com/JuliaDiff/DifferentiationInterface.jl/tree/ed5655a90bf9f3a6092904070d353a9d705ebdc4/DifferentiationInterfaceTest/src/scenarios) (especially [`src/scenarios/default.jl`](https://github.com/JuliaDiff/DifferentiationInterface.jl/blob/ed5655a90bf9f3a6092904070d353a9d705ebdc4/DifferentiationInterfaceTest/src/scenarios/default.jl) and [`src/scenarios/modify.jl`](https://github.com/JuliaDiff/DifferentiationInterface.jl/blob/ed5655a90bf9f3a6092904070d353a9d705ebdc4/DifferentiationInterfaceTest/src/scenarios/modify.jl)) and in package extensions. | ||
| The structure of a `Scenario` is defined in [`src/scenarios/scenario.jl`](https://github.com/JuliaDiff/DifferentiationInterface.jl/blob/ed5655a90bf9f3a6092904070d353a9d705ebdc4/DifferentiationInterfaceTest/src/scenarios/scenario.jl). | ||
|
|
||
| Scenario generation relies on internals of DifferentiationInterfaceTest, which is why its version is pinned in the `Project.toml`. | ||
|
|
||
| ## Interpreting test errors | ||
|
|
||
| The most common test error you will see looks like | ||
|
|
||
| ```julia | ||
| Correctness: Test Failed at .../src/tests/correctness_eval.jl:... | ||
| Expression: res1_out1_noval ≈ scen.res1 | ||
| ``` | ||
|
|
||
| Each test scenario `scen` contains a first-order result `res1` and a second-order result `res2`, which are the reference values we compare our autodiff results (i.e. the output of `DI.gradient` or `DI.jacobian`) against. | ||
| The suffixes of the left-hand term are defined as follows: | ||
|
|
||
| - `_out` for the output of the operator, `_in` for the input if it is in-place | ||
| - `1` for the first call to the operator, `2` for the second call (which is used to check that the preparation object has not been altered and can safely be reused) | ||
| - `_val` if the operator also returns the value of the function (like `DI.value_and_gradient`), `_noval` otherwise | ||
|
|
||
| As you can see, several variants of each operator are tested, so a single bug will give rise to many different errors. In addition, different preparation mechanisms are also cycled through. | ||
| The testset summary at the end of the CI log is probably the right place to start hunting down issues. | ||
|
|
||
| ## What to do if a test fails | ||
|
|
||
| Open an issue on the DI repo with a link to the relevant PR or CI log. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| using ADTypes: AutoEnzyme | ||
| using DifferentiationInterface: DifferentiationInterface | ||
| using DifferentiationInterfaceTest: | ||
| default_scenarios, | ||
| sparse_scenarios, | ||
| static_scenarios, | ||
| test_differentiation, | ||
| function_place, | ||
| operator_place, | ||
| FIRST_ORDER, | ||
| SECOND_ORDER, | ||
| Scenario | ||
| using Enzyme: Enzyme | ||
| using EnzymeCore: Forward, Reverse, Const, Duplicated | ||
| using StaticArrays: StaticArrays | ||
| using Test | ||
|
|
||
| logging = get(ENV, "CI", "false") == "false" | ||
|
|
||
| function remove_matrices(scens::Vector{<:Scenario}) # TODO: remove | ||
| return filter(s -> s.x isa Union{Number, AbstractVector} && s.y isa Union{Number, AbstractVector}, scens) | ||
| end | ||
|
|
||
| backends = [ | ||
| AutoEnzyme(; function_annotation = Const), | ||
| AutoEnzyme(; mode = Forward), | ||
| AutoEnzyme(; mode = Reverse), | ||
| ] | ||
|
|
||
| duplicated_backends = [ | ||
| AutoEnzyme(; mode = Forward, function_annotation = Duplicated), | ||
| AutoEnzyme(; mode = Reverse, function_annotation = Duplicated), | ||
| ] | ||
|
|
||
| @testset verbose = true "DifferentiationInterface integration" begin | ||
| test_differentiation( | ||
| backends, | ||
| default_scenarios(; include_constantified = true); | ||
| excluded = SECOND_ORDER, | ||
| logging, | ||
| testset_name = "Generic first order", | ||
| ) | ||
|
|
||
| test_differentiation( | ||
| backends[1], | ||
| remove_matrices(default_scenarios(; include_constantified = true)); | ||
| excluded = FIRST_ORDER, | ||
| logging, | ||
| testset_name = "Generic second order", | ||
| ) | ||
|
|
||
| test_differentiation( | ||
| backends[2], | ||
| remove_matrices( | ||
| default_scenarios(; | ||
| include_normal = false, | ||
| include_cachified = true, | ||
| include_constantorcachified = true, | ||
| use_tuples = true, | ||
| ) | ||
| ); | ||
| excluded = SECOND_ORDER, | ||
| logging, | ||
| testset_name = "Caches", | ||
| ) | ||
|
|
||
| test_differentiation( | ||
| duplicated_backends, | ||
| remove_matrices(default_scenarios(; include_normal = false, include_closurified = true)); | ||
| excluded = SECOND_ORDER, | ||
| logging, | ||
| testset_name = "Closures", | ||
| ) | ||
|
|
||
| filtered_static_scenarios = filter(remove_matrices(static_scenarios())) do s | ||
| operator_place(s) == :out && function_place(s) == :out | ||
| end | ||
|
|
||
| test_differentiation( | ||
| backends[2:3], | ||
| filtered_static_scenarios; | ||
| excluded = SECOND_ORDER, | ||
| logging, | ||
| testset_name = "Static arrays", | ||
| ) | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,11 @@ | ||
| [deps] | ||
| DynamicExpressions = "a40a106e-89c9-4ca8-8020-a735e8728b6b" | ||
| Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" | ||
| EnzymeCore = "f151be2c-9106-41f4-ab19-57ee4f262869" | ||
|
|
||
| [sources] | ||
| Enzyme = { path = "../../.." } | ||
| EnzymeCore = { path = "../../../lib/EnzymeCore" } | ||
|
|
||
| [compat] | ||
| DynamicExpressions = "=0.18.5" |
Uh oh!
There was an error while loading. Please reload this page.