Skip to content

Enzyme reverse-mode autodiff extension#867

Open
danvinci wants to merge 2 commits into
JuliaGPU:mainfrom
danvinci:enzyme-metal-ext
Open

Enzyme reverse-mode autodiff extension#867
danvinci wants to merge 2 commits into
JuliaGPU:mainfrom
danvinci:enzyme-metal-ext

Conversation

@danvinci

Copy link
Copy Markdown

Adds ext/EnzymeCoreExt.jl: Enzyme reverse-mode autodiff for Metal, mirroring CUDA.jl's and AMDGPU.jl's extensions. Implements the autodiff side of #414.

What differentiates on Metal:

  • user-written @metal kernels - via device-side split-mode autodiff (meta_kernels.jl); the generic core, same shape as AMDGPU's AMDGPUEnzymeCoreExt
  • sum reductions
  • matrix multiply (A*B) - closed-form reverse, since MPS/MPSGraph is opaque to Enzyme

device / global_queue / synchronize are marked inactive to keep Enzyme out of Metal's Objective-C launch path; CUDA/AMDGPU need no equivalent.

Tested in test/enzyme.jl: sum, A*B, and a hand-written kernel match closed-form gradients.

Draft - open items:

  • GPUArrays broadcast (y .= f.(x)) isn't covered yet; its reverse needs per-element autodiff of the fused broadcast. Maintainer input welcome.
  • matmul needs set_runtime_activity.

Surfaced an unrelated Enzyme GPU tape_type bug while building this: EnzymeAD/Enzyme.jl#3265 (not required here - the launch rules pass explicit ModifiedBetween, as CUDA/AMDGPU do).

Drafted with Opus 4.8, review welcome.

@codecov

codecov Bot commented Jun 30, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.51%. Comparing base (59e377f) to head (458dd08).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #867      +/-   ##
==========================================
+ Coverage   86.25%   86.51%   +0.25%     
==========================================
  Files          76       76              
  Lines        5130     5132       +2     
==========================================
+ Hits         4425     4440      +15     
+ Misses        705      692      -13     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@danvinci danvinci marked this pull request as ready for review June 30, 2026 04:15

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Metal Benchmarks

Details
Benchmark suite Current: 458dd08 Previous: 59e377f Ratio
array/accumulate/Float32/1d 568542 ns 573625 ns 0.99
array/accumulate/Float32/dims=1 568000 ns 571125 ns 0.99
array/accumulate/Float32/dims=1L 8858437.5 ns 8850292 ns 1.00
array/accumulate/Float32/dims=2 621500 ns 625125 ns 0.99
array/accumulate/Float32/dims=2L 3347250 ns 3358312 ns 1.00
array/accumulate/Int64/1d 895875 ns 894208 ns 1.00
array/accumulate/Int64/dims=1 1101958 ns 1095792 ns 1.01
array/accumulate/Int64/dims=1L 9576687 ns 9580896 ns 1.00
array/accumulate/Int64/dims=2 1463937.5 ns 1462208 ns 1.00
array/accumulate/Int64/dims=2L 6597416 ns 6584667 ns 1.00
array/broadcast 368959 ns 364209 ns 1.01
array/construct 3334 ns 3334 ns 1
array/permutedims/2d 630667 ns 633458 ns 1.00
array/permutedims/3d 1094709 ns 1098354 ns 1.00
array/permutedims/4d 1652250 ns 1590750.5 ns 1.04
array/private/copy 400854.5 ns 407917 ns 0.98
array/private/copyto!/cpu_to_gpu 378208 ns 382125 ns 0.99
array/private/copyto!/gpu_to_cpu 379770.5 ns 377459 ns 1.01
array/private/copyto!/gpu_to_gpu 355750 ns 357750 ns 0.99
array/private/iteration/findall/bool 1142541 ns 1140208 ns 1.00
array/private/iteration/findall/int 1280250 ns 1280458 ns 1.00
array/private/iteration/findfirst/bool 1382437.5 ns 1428334 ns 0.97
array/private/iteration/findfirst/int 1489687.5 ns 1466499.5 ns 1.02
array/private/iteration/findmin/1d 1576625 ns 1567125 ns 1.01
array/private/iteration/findmin/2d 1273125 ns 1270709 ns 1.00
array/private/iteration/logical 1892104.5 ns 1933750 ns 0.98
array/private/iteration/scalar 2802417 ns 2445416 ns 1.15
array/random/rand/Float32 622334 ns 616666 ns 1.01
array/random/rand/Int64 631291 ns 629708 ns 1.00
array/random/rand!/Float32 522479 ns 530625 ns 0.98
array/random/rand!/Int64 490500 ns 495291.5 ns 0.99
array/random/randn/Float32 565104 ns 570667 ns 0.99
array/random/randn!/Float32 481291 ns 477000 ns 1.01
array/reductions/mapreduce/Float32/1d 692833 ns 715520.5 ns 0.97
array/reductions/mapreduce/Float32/dims=1 487000 ns 492000 ns 0.99
array/reductions/mapreduce/Float32/dims=1L 689083 ns 689083 ns 1
array/reductions/mapreduce/Float32/dims=2 492270.5 ns 494792 ns 0.99
array/reductions/mapreduce/Float32/dims=2L 1339417 ns 1335459 ns 1.00
array/reductions/mapreduce/Int64/1d 911500 ns 943459 ns 0.97
array/reductions/mapreduce/Int64/dims=1 830208.5 ns 812625 ns 1.02
array/reductions/mapreduce/Int64/dims=1L 1075250 ns 1075667 ns 1.00
array/reductions/mapreduce/Int64/dims=2 965500 ns 987541 ns 0.98
array/reductions/mapreduce/Int64/dims=2L 2168395.5 ns 2168458 ns 1.00
array/reductions/reduce/Float32/1d 688375 ns 693083 ns 0.99
array/reductions/reduce/Float32/dims=1 478895.5 ns 496312.5 ns 0.96
array/reductions/reduce/Float32/dims=1L 687625 ns 687979.5 ns 1.00
array/reductions/reduce/Float32/dims=2 389792 ns 395834 ns 0.98
array/reductions/reduce/Float32/dims=2L 490375 ns 485542 ns 1.01
array/reductions/reduce/Int64/1d 915333 ns 962083 ns 0.95
array/reductions/reduce/Int64/dims=1 826458 ns 814541.5 ns 1.01
array/reductions/reduce/Int64/dims=1L 1071167 ns 1069500 ns 1.00
array/reductions/reduce/Int64/dims=2 978125 ns 973542 ns 1.00
array/reductions/reduce/Int64/dims=2L 2150417 ns 2149542 ns 1.00
array/shared/copy 154208 ns 154083 ns 1.00
array/shared/copyto!/cpu_to_gpu 39250 ns 40708 ns 0.96
array/shared/copyto!/gpu_to_cpu 40625 ns 41000 ns 0.99
array/shared/copyto!/gpu_to_gpu 41416 ns 41208 ns 1.01
array/shared/iteration/findall/bool 1148292 ns 1148500 ns 1.00
array/shared/iteration/findall/int 1287541 ns 1285750 ns 1.00
array/shared/iteration/findfirst/bool 1110791 ns 1119667 ns 0.99
array/shared/iteration/findfirst/int 1174709 ns 1207312.5 ns 0.97
array/shared/iteration/findmin/1d 1323166 ns 1317938 ns 1.00
array/shared/iteration/findmin/2d 1268583 ns 1269625 ns 1.00
array/shared/iteration/logical 1715042 ns 1709354 ns 1.00
array/shared/iteration/scalar 3406.25 ns 3614.625 ns 0.94
integration/byval/reference 1135542 ns 1141958 ns 0.99
integration/byval/slices=1 1134500 ns 1136875 ns 1.00
integration/byval/slices=2 2053541 ns 2055750 ns 1.00
integration/byval/slices=3 7327625 ns 8460958 ns 0.87
integration/metaldevrt 442333 ns 451500 ns 0.98
kernel/indexing 356167 ns 351792 ns 1.01
kernel/indexing_checked 539458 ns 534209 ns 1.01
kernel/launch 1970.8 ns 1975 ns 1.00
kernel/rand 518042 ns 528250 ns 0.98
latency/import 1782315667 ns 1791534292 ns 0.99
latency/precompile 39295008687.5 ns 39637308833.5 ns 0.99
latency/ttfp 2114608917 ns 2124080375 ns 1.00
metal/synchronization/context 535.4041450777202 ns 523.9637305699482 ns 1.02
metal/synchronization/stream 274.36102236421726 ns 277.5974025974026 ns 0.99

This comment was automatically generated by workflow using github-action-benchmark.

@danvinci danvinci marked this pull request as draft July 6, 2026 00:28
@danvinci danvinci marked this pull request as ready for review July 6, 2026 00:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant