diff --git a/.github/workflows/Test.yml b/.github/workflows/Test.yml index 3a82f29a4..83239580a 100644 --- a/.github/workflows/Test.yml +++ b/.github/workflows/Test.yml @@ -16,64 +16,6 @@ concurrency: cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} jobs: - test-DI-Core: - name: ${{ matrix.version }} - DI Core (${{ matrix.group }}) - runs-on: ubuntu-latest - if: ${{ !contains(github.event.pull_request.labels.*.name, 'skipci') }} - timeout-minutes: 180 - permissions: - # needed to allow julia-actions/cache to proactively delete old caches that it has created - actions: write - contents: read - strategy: - fail-fast: false # TODO: toggle - matrix: - version: - - '1.10' - - '1.11' - - '1.12' - group: - - Internals - - SimpleFiniteDiff - - ZeroBackends - skip_past: - - ${{ github.event.pull_request.draft }} - exclude: - - skip_past: true - version: '1.10' - - skip_past: true - version: '1.11' - env: - JULIA_DI_TEST_TYPE: 'Core' - JULIA_DI_TEST_GROUP: ${{ matrix.group }} - JULIA_DI_PR_DRAFT: ${{ github.event.pull_request.draft }} - steps: - - uses: actions/checkout@v6 - - uses: julia-actions/setup-julia@v3 - with: - version: ${{ matrix.version }} - arch: x64 - - uses: julia-actions/cache@v3 - - name: Install dependencies & run tests - run: julia --color=yes -e ' using Pkg; - Pkg.activate("./DifferentiationInterface/test"); if VERSION < v"1.11"; - Pkg.rm("DifferentiationInterfaceTest"); Pkg.resolve(); else; - Pkg.develop(; path="./DifferentiationInterfaceTest"); end; - Pkg.activate("./DifferentiationInterface"); test_kwargs = (; - allow_reresolve=false, coverage=true); if ENV["JULIA_DI_PR_DRAFT"] == - "true"; Pkg.test("DifferentiationInterface"; julia_args=["-O1"], - test_kwargs...); else; Pkg.test("DifferentiationInterface"; - test_kwargs...); end;' - - uses: julia-actions/julia-processcoverage@v1 - with: - directories: ./DifferentiationInterface/src,./DifferentiationInterface/ext,./DifferentiationInterface/test - - uses: codecov/codecov-action@v6 - with: - files: lcov.info - flags: DI - token: ${{ secrets.CODECOV_TOKEN }} - fail_ci_if_error: false - test-DI-Backend: name: ${{ matrix.version }} - DI Back (${{ matrix.group }}) runs-on: ubuntu-latest @@ -91,24 +33,7 @@ jobs: - '1.11' - '1.12' group: - - ChainRules - - DifferentiateWith - # - Diffractor - Enzyme - - FastDifferentiation - - FiniteDiff - - FiniteDifferences - - ForwardDiff - - GTPSA - - HyperHessians - - Mooncake - - Mooncake-old - - PolyesterForwardDiff - - ReverseDiff - - SparsityDetector - - Symbolics - - Tracker - - Zygote skip_past: - ${{ github.event.pull_request.draft }} exclude: @@ -139,7 +64,7 @@ jobs: include("./DifferentiationInterface/test/Back/run_backend.jl");' - name: Install dependencies & run tests (not draft) if: ${{ !github.event.pull_request.draft }} - run: julia -O1 --code-coverage=user --color=yes -e ' using Pkg; group = + run: julia --code-coverage=user --color=yes -e ' using Pkg; group = ENV["JULIA_DI_TEST_GROUP"]; Pkg.activate("./DifferentiationInterface/test/Back/$group"); Pkg.develop([PackageSpec(path="./DifferentiationInterface"), @@ -154,60 +79,3 @@ jobs: flags: DI token: ${{ secrets.CODECOV_TOKEN }} fail_ci_if_error: false - - test-DIT: - name: ${{ matrix.version }} - DIT (${{ matrix.group }}) - runs-on: ubuntu-latest - if: ${{ !contains(github.event.pull_request.labels.*.name, 'skipci') }} - timeout-minutes: 60 - permissions: - # needed to allow julia-actions/cache to proactively delete old caches that it has created - actions: write - contents: read - strategy: - fail-fast: false # TODO: toggle - matrix: - version: - - '1.10' - - '1.11' - - '1.12' - group: - - Formalities - - Zero - - Standard - - Weird - skip_past: - - ${{ github.event.pull_request.draft }} - exclude: - - skip_past: true - version: '1.10' - - skip_past: true - version: '1.11' - env: - JULIA_DIT_TEST_GROUP: ${{ matrix.group }} - JULIA_DI_PR_DRAFT: ${{ github.event.pull_request.draft }} - steps: - - uses: actions/checkout@v6 - - uses: julia-actions/setup-julia@v3 - with: - version: ${{ matrix.version }} - arch: x64 - - uses: julia-actions/cache@v3 - - name: Install dependencies & run tests - run: - julia --project=./DifferentiationInterfaceTest --color=yes -e ' using Pkg; - Pkg.Registry.update(); Pkg.develop(path="./DifferentiationInterface"); - if ENV["JULIA_DI_PR_DRAFT"] == "true"; - Pkg.test("DifferentiationInterfaceTest"; allow_reresolve=false, - coverage=true, julia_args=["-O1"]); else; - Pkg.test("DifferentiationInterfaceTest"; allow_reresolve=false, - coverage=true); end;' - - uses: julia-actions/julia-processcoverage@v1 - with: - directories: ./DifferentiationInterfaceTest/src,./DifferentiationInterfaceTest/ext,./DifferentiationInterfaceTest/test - - uses: codecov/codecov-action@v6 - with: - files: lcov.info - flags: DIT - token: ${{ secrets.CODECOV_TOKEN }} - fail_ci_if_error: false diff --git a/DifferentiationInterface/test/Back/Enzyme/test.jl b/DifferentiationInterface/test/Back/Enzyme/test.jl index d43019d43..834acaa18 100644 --- a/DifferentiationInterface/test/Back/Enzyme/test.jl +++ b/DifferentiationInterface/test/Back/Enzyme/test.jl @@ -1,199 +1,24 @@ -include("../../testutils.jl") - -using ADTypes: ADTypes -using DifferentiationInterface, DifferentiationInterfaceTest -import DifferentiationInterfaceTest as DIT -using Enzyme: Enzyme -using LinearAlgebra -using StaticArrays +using DifferentiationInterface +import Enzyme using Test -using ExplicitImports -check_no_implicit_imports(DifferentiationInterface) - -backends = [ - AutoEnzyme(; mode = nothing), - AutoEnzyme(; mode = Enzyme.Forward), - AutoEnzyme(; mode = Enzyme.Reverse), - AutoEnzyme(; mode = nothing, function_annotation = Enzyme.Const), -] - -duplicated_backends = [ - AutoEnzyme(; mode = Enzyme.Forward, function_annotation = Enzyme.Duplicated), - AutoEnzyme(; mode = Enzyme.Reverse, function_annotation = Enzyme.Duplicated), -] - -@testset "Checks" begin - @testset "Check $(typeof(backend))" for backend in backends - @test check_available(backend) - @test check_inplace(backend) - end -end; - -@testset "First order" begin - test_differentiation( - backends, default_scenarios(); excluded = SECOND_ORDER, logging = LOGGING - ) - - test_differentiation( - backends[1:3], - default_scenarios(; include_normal = false, include_constantified = true); - excluded = SECOND_ORDER, - logging = LOGGING, - ) - - test_differentiation( - backends[2:3], - default_scenarios(; - include_normal = false, - include_cachified = true, - include_constantorcachified = true, - use_tuples = true, - ); - excluded = SECOND_ORDER, - logging = LOGGING, - ) - - test_differentiation( - duplicated_backends, - default_scenarios(; include_normal = false, include_closurified = true); - excluded = SECOND_ORDER, - logging = LOGGING, - ) -end - -@testset "Second order" begin - test_differentiation( - AutoEnzyme(), - default_scenarios(; include_constantified = true, include_cachified = true); - excluded = vcat(FIRST_ORDER, :hvp, :hessian), - logging = LOGGING, - ) - - test_differentiation( - AutoEnzyme(), - default_scenarios(; include_constantified = true); - excluded = vcat(FIRST_ORDER, :second_derivative), - logging = LOGGING, - ) +backend = SecondOrder( + AutoEnzyme(; mode = Enzyme.set_runtime_activity(Enzyme.Forward)), + AutoEnzyme(; mode = Enzyme.set_runtime_activity(Enzyme.Reverse)) +) - test_differentiation( - # TODO: simplify when https://github.com/EnzymeAD/Enzyme.jl/issues/2854 and https://github.com/EnzymeAD/Enzyme.jl/issues/2925 are fixed - if VERSION >= v"1.11" - SecondOrder( - AutoEnzyme(; mode = Enzyme.set_runtime_activity(Enzyme.Forward)), - AutoEnzyme(; mode = Enzyme.set_runtime_activity(Enzyme.Reverse)) - ) - else - AutoEnzyme() - end, - default_scenarios(; include_normal = false, include_constantified = false, include_cachified = true); - excluded = vcat(FIRST_ORDER, :second_derivative), - logging = LOGGING, - ) - - test_differentiation( - [ - SecondOrder( - AutoEnzyme(; mode = Enzyme.Reverse), AutoEnzyme(; mode = Enzyme.Forward) - ), - ], - default_scenarios(; include_constantified = true, include_cachified = true); - excluded = FIRST_ORDER, - logging = LOGGING, - ) -end - -@testset "Sparse" begin - test_differentiation( - MyAutoSparse.(AutoEnzyme(; function_annotation = Enzyme.Const)), - if VERSION < v"1.11" - sparse_scenarios() - else - filter(s -> s.x isa AbstractVector, sparse_scenarios()) - end; - sparsity = true, - logging = LOGGING, - ) -end - -@testset "Static" begin - filtered_static_scenarios = filter(static_scenarios()) do s - DIT.operator_place(s) == :out && DIT.function_place(s) == :out - end - - test_differentiation( - [AutoEnzyme(; mode = Enzyme.Forward), AutoEnzyme(; mode = Enzyme.Reverse)], - filtered_static_scenarios; - excluded = SECOND_ORDER, - logging = LOGGING, - ) +struct StoreInCache{F} + f::F end -@testset "Coverage" begin - # ConstantOrCache without cache - f_nocontext(x, p) = x - @test I == DifferentiationInterface.jacobian( - f_nocontext, AutoEnzyme(; mode = Enzyme.Forward), rand(10), ConstantOrCache(nothing) - ) - @test I == DifferentiationInterface.jacobian( - f_nocontext, AutoEnzyme(; mode = Enzyme.Reverse), rand(10), ConstantOrCache(nothing) - ) +function (sc::StoreInCache)(x, y_cache) + y_cache[1] = sc.f(x) + return y_cache[1] end -@testset "Hints" begin - @testset "MutabilityError" begin - f = let - cache = [0.0] - x -> sum(copyto!(cache, x)) - end - - e = nothing - try - gradient(f, AutoEnzyme(), [1.0]) - catch e - end - msg = sprint(showerror, e) - @test occursin("AutoEnzyme", msg) - @test occursin("function_annotation", msg) - @test occursin("ADTypes", msg) - end - - @testset "RuntimeActivityError" begin - function g(active_var, constant_var, cond) - if cond - return active_var - else - return constant_var - end - end - - function h(active_var, constant_var, cond) - return [g(active_var, constant_var, cond), g(active_var, constant_var, cond)] - end - - e = nothing - try - pushforward( - h, - AutoEnzyme(; mode = Enzyme.Forward), - [1.0], - ([1.0],), - Constant([1.0]), - Constant(true), - ) - catch e - end - msg = sprint(showerror, e) - @test_broken occursin("AutoEnzyme", msg) - @test_broken occursin("ADTypes", msg) - end -end +f(x::AbstractArray) = sum(vec(x .^ 4) .* transpose(vec(x .^ 6))) -@testset "Empty arrays" begin - test_differentiation( - [AutoEnzyme(; mode = Enzyme.Forward), AutoEnzyme(; mode = Enzyme.Reverse)], - empty_scenarios(); - excluded = [:jacobian], - ) -end; +x = [1.0;;] +dx = [3.0;;] +c = similar(x) +@test_nowarn gradient_and_hvp(StoreInCache(f), backend, x, (dx,), Cache(x))