Skip to content

GPU Refactor: Add array_type parameter and GPU extensions - #43

Open
hakkelt wants to merge 10 commits into
kul-optec:masterfrom
hakkelt:gpu-refactor
Open

GPU Refactor: Add array_type parameter and GPU extensions#43
hakkelt wants to merge 10 commits into
kul-optec:masterfrom
hakkelt:gpu-refactor

Conversation

@hakkelt

@hakkelt hakkelt commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

This PR introduces a comprehensive GPU refactoring, plus test-coverage, CI-stability, and agent-guidance follow-ups.

GPU support

  • Adds the array_type parameter to support multiple backends.
  • Introduces new GPU extensions for various operators.
  • Modernizes the test infrastructure using GPUEnv for backend-agnostic testing.
  • Excludes JLArrays from FFTW-backed GPU tests (DFT/RDFT/IRDFT, Conv, Xcorr, Filt, MIMOFilt) — JLArray's StridedArray conformance routes AbstractFFTs.plan_fft into FFTW's raw-pointer CPU path, which JLArray intentionally rejects.

Test coverage & CI stability

  • Improves test coverage across nonlinear operations and edge cases.
  • Adds copy_operator coverage for Sum, DiagOp, Variation, BroadCast, OperatorWrapper, HadamardProd, and HCAT's get_slicing_expr, closing codecov patch-coverage gaps.
  • Removes non-portable !== struct-identity assertions from copy_operator tests (Julia's immutable-struct === semantics differ across versions and broke the 1.10 LTS job).
  • Removes AcceleratedDCTs from test/Project.toml (Julia ≥1.11-only; added dynamically at runtime instead, since a static listing broke 1.10 LTS dependency resolution).
  • Disables Aqua's persistent_tasks check.

Agent guidance

  • Consolidates .github/agents, .github/skills, and .github/instructions into a single AGENTS.md, with a CLAUDE.md symlink.
  • Splits GPU-extension conventions into ext/GpuExt/AGENTS.md and the long-running test/coverage/benchmark workflow into a skill, so both load only when relevant instead of always.

@hakkelt
hakkelt marked this pull request as draft July 17, 2026 16:35
…t merge

Adds AcceleratedDCTs test dependency, disables Aqua's persistent_tasks
check, and carries forward the test coverage expansion, test refactors,
and small dead-code/API cleanups developed on gpu-refactor after the
GPU-support work was squash-merged upstream as 861af22.
Merge .github/agents, .github/skills, and .github/instructions into one
flat AGENTS.md and add a CLAUDE.md symlink, removing the duplication
across the router file and its six referenced documents.
@github-actions

github-actions Bot commented Aug 11, 2026

Copy link
Copy Markdown

Benchmark Results (Julia v1.12.6)

No significant performance or memory regressions detected.

Time benchmarks
Benchmark base head Ratio (base/head)
batching/SimpleBatchOp/adjoint-single 52.1 ± 3.1 μs 49.2 ± 5.6 μs 1.06 ± 0.27
batching/SimpleBatchOp/forward-single 45 ± 2.8 μs 41.7 ± 4.8 μs 1.08 ± 0.28
batching/SpreadingBatchOp/adjoint-single 27.7 ± 1.5 μs 30.4 ± 2.1 μs 0.911 ± 0.16
batching/SpreadingBatchOp/forward-single 25.3 ± 1.3 μs 25.5 ± 1.6 μs 0.989 ± 0.16
calculus/AffineAdd/adjoint 7.02 ± 0.28 μs 6.95 ± 0.24 μs 1.01 ± 0.11
calculus/AffineAdd/forward 14.1 ± 0.74 μs 14.2 ± 1.1 μs 0.996 ± 0.18
calculus/Ax_mul_Bx/forward 20.4 ± 2.2 μs 19.7 ± 1.4 μs 1.03 ± 0.27
calculus/Ax_mul_Bx/jacobian-adjoint 56.9 ± 2.1 μs 52.7 ± 3.3 μs 1.08 ± 0.16
calculus/Ax_mul_Bxt/forward 19.4 ± 1.4 μs 20.1 ± 1.2 μs 0.967 ± 0.18
calculus/Ax_mul_Bxt/jacobian-adjoint 46.9 ± 2.1 μs 47.8 ± 2.3 μs 0.981 ± 0.13
calculus/Axt_mul_Bx/forward 23.3 ± 1.5 μs 23.4 ± 1.3 μs 0.995 ± 0.16
calculus/Axt_mul_Bx/jacobian-adjoint 50.3 ± 2.2 μs 51.2 ± 3.1 μs 0.981 ± 0.15
calculus/BroadCast/identity-single 110 ± 18 μs 109 ± 20 μs 1.01 ± 0.5
calculus/BroadCast/operator-single-adjoint 1.67 ± 0.082 μs 1.65 ± 0.077 μs 1.01 ± 0.14
calculus/BroadCast/operator-single-forward 452 ± 52 ns 432 ± 50 ns 1.05 ± 0.34
calculus/Compose/adjoint 9.82 ± 0.6 μs 10.1 ± 0.55 μs 0.97 ± 0.16
calculus/Compose/forward 10.1 ± 1 μs 10.7 ± 0.8 μs 0.946 ± 0.24
calculus/DCAT/adjoint 20.7 ± 2 μs 22 ± 2.6 μs 0.94 ± 0.28
calculus/DCAT/forward 23.1 ± 2.3 μs 24 ± 3.7 μs 0.963 ± 0.35
calculus/HCAT/adjoint 20.2 ± 2.1 μs 22.3 ± 1.7 μs 0.906 ± 0.24
calculus/HCAT/forward 47 ± 6.3 μs 50.9 ± 3.9 μs 0.922 ± 0.29
calculus/HadamardProd/forward 785 ± 13 μs 771 ± 14 μs 1.02 ± 0.05
calculus/HadamardProd/jacobian-adjoint 881 ± 16 μs 870 ± 15 μs 1.01 ± 0.05
calculus/Jacobian/sigmoid-adjoint 151 ± 5.5 μs 153 ± 4.7 μs 0.991 ± 0.094
calculus/Reshape/adjoint 6.86 ± 0.18 μs 6.94 ± 0.23 μs 0.989 ± 0.083
calculus/Reshape/forward 6.68 ± 0.14 μs 6.76 ± 0.17 μs 0.988 ± 0.066
calculus/Scale/adjoint 12.8 ± 0.29 μs 12.9 ± 0.33 μs 0.987 ± 0.067
calculus/Scale/forward 14.2 ± 0.27 μs 14.5 ± 0.3 μs 0.983 ± 0.055
calculus/Sum/adjoint 45.5 ± 4.2 μs 46.7 ± 5 μs 0.974 ± 0.27
calculus/Sum/forward 45.5 ± 3.9 μs 46.3 ± 4.7 μs 0.983 ± 0.26
calculus/VCAT/adjoint 48.5 ± 5.1 μs 50.2 ± 7.2 μs 0.967 ± 0.34
calculus/VCAT/forward 20.1 ± 1.8 μs 20.3 ± 2.1 μs 0.993 ± 0.27
dspoperators/Filt/adjoint 277 ± 6.5 μs 282 ± 21 μs 0.985 ± 0.15
dspoperators/Filt/forward 307 ± 6 μs 278 ± 10 μs 1.1 ± 0.093
dspoperators/MIMOFilt/adjoint 199 ± 3.8 μs 236 ± 11 μs 0.843 ± 0.088
dspoperators/MIMOFilt/forward 201 ± 4.1 μs 203 ± 4.7 μs 0.99 ± 0.061
dspoperators/Xcorr/adjoint 55.4 ± 1.4 μs 57.7 ± 1.8 μs 0.96 ± 0.077
dspoperators/Xcorr/forward 541 ± 47 μs 592 ± 86 μs 0.914 ± 0.31
fftwoperators/DFT/adjoint 168 ± 11 μs 166 ± 11 μs 1.01 ± 0.18
fftwoperators/DFT/forward 140 ± 13 μs 138 ± 12 μs 1.01 ± 0.26
linearoperators/DiagOp/adjoint-single 645 ± 18 μs 653 ± 18 μs 0.987 ± 0.078
linearoperators/DiagOp/adjoint-threaded 378 ± 13 μs 372 ± 13 μs 1.02 ± 0.1
linearoperators/DiagOp/forward-single 665 ± 18 μs 674 ± 15 μs 0.987 ± 0.07
linearoperators/DiagOp/forward-threaded 345 ± 11 μs 346 ± 12 μs 0.998 ± 0.09
linearoperators/Eye/forward 909 ± 24 μs 909 ± 37 μs 0.999 ± 0.097
linearoperators/FiniteDiff/adjoint 898 ± 30 μs 892 ± 15 μs 1.01 ± 0.075
linearoperators/FiniteDiff/forward 980 ± 37 μs 971 ± 17 μs 1.01 ± 0.084
linearoperators/GetIndex/adjoint 1.96 ± 0.021 ms 1.98 ± 0.019 ms 0.988 ± 0.029
linearoperators/GetIndex/forward 1.17 ± 0.022 ms 1.17 ± 0.029 ms 0.995 ± 0.061
linearoperators/LBFGS/mul 58.2 ± 1.8 μs 59.6 ± 2.2 μs 0.976 ± 0.094
linearoperators/LBFGS/update 9.64 ± 0.38 μs 9.76 ± 0.49 μs 0.988 ± 0.13
linearoperators/LMatrixOp/adjoint 743 ± 1.5e+02 μs 874 ± 15 μs 0.85 ± 0.33
linearoperators/LMatrixOp/forward 182 ± 9.4 μs 187 ± 13 μs 0.974 ± 0.17
linearoperators/MatrixOp/adjoint 140 ± 4.9 μs 145 ± 5.8 μs 0.969 ± 0.1
linearoperators/MatrixOp/forward 137 ± 5.1 μs 139 ± 6 μs 0.984 ± 0.11
linearoperators/MyLinOp/adjoint 641 ± 21 μs 634 ± 15 μs 1.01 ± 0.081
linearoperators/MyLinOp/forward 667 ± 15 μs 664 ± 12 μs 1.01 ± 0.059
linearoperators/Variation/adjoint-single 797 ± 14 μs 793 ± 14 μs 1 ± 0.05
linearoperators/Variation/forward-single 233 ± 49 μs 239 ± 43 μs 0.975 ± 0.54
linearoperators/ZeroPad/adjoint 161 ± 14 μs 159 ± 17 μs 1.01 ± 0.28
linearoperators/ZeroPad/forward 189 ± 40 μs 193 ± 36 μs 0.982 ± 0.55
linearoperators/Zeros/forward 1.27 ± 0.013 ms 1.26 ± 0.075 ms 1.01 ± 0.12
nfftoperators/NFFTOp/adjoint 259 ± 7.5 μs 259 ± 7.3 μs 1 ± 0.081
nfftoperators/NFFTOp/forward 217 ± 6.2 μs 215 ± 5.9 μs 1.01 ± 0.08
nonlinearoperators/Atan/forward 379 ± 7.3 μs 379 ± 7.6 μs 1 ± 0.056
nonlinearoperators/Atan/jacobian-adjoint 21.4 ± 0.36 μs 21.6 ± 0.39 μs 0.991 ± 0.049
nonlinearoperators/Cos/forward 364 ± 5.4 μs 363 ± 7.1 μs 1 ± 0.049
nonlinearoperators/Cos/jacobian-adjoint 412 ± 13 μs 412 ± 14 μs 1 ± 0.09
nonlinearoperators/Exp/forward 450 ± 12 μs 440 ± 11 μs 1.02 ± 0.075
nonlinearoperators/Exp/jacobian-adjoint 519 ± 17 μs 504 ± 15 μs 1.03 ± 0.092
nonlinearoperators/Pow/forward 674 ± 17 μs 601 ± 16 μs 1.12 ± 0.084
nonlinearoperators/Pow/jacobian-adjoint 420 ± 17 μs 422 ± 24 μs 0.996 ± 0.14
nonlinearoperators/Sech/forward 228 ± 4.5 μs 217 ± 4.4 μs 1.05 ± 0.06
nonlinearoperators/Sech/jacobian-adjoint 568 ± 12 μs 541 ± 14 μs 1.05 ± 0.07
nonlinearoperators/Sigmoid/forward 251 ± 5.4 μs 251 ± 5.7 μs 0.998 ± 0.062
nonlinearoperators/Sigmoid/jacobian-adjoint 305 ± 11 μs 307 ± 9.2 μs 0.994 ± 0.091
nonlinearoperators/Sin/forward 364 ± 6.9 μs 360 ± 6.5 μs 1.01 ± 0.053
nonlinearoperators/Sin/jacobian-adjoint 385 ± 7.5 μs 375 ± 7.1 μs 1.03 ± 0.056
nonlinearoperators/SoftMax/forward 303 ± 6.8 μs 306 ± 9.7 μs 0.99 ± 0.077
nonlinearoperators/SoftMax/jacobian-adjoint 369 ± 11 μs 371 ± 12 μs 0.995 ± 0.089
nonlinearoperators/SoftPlus/forward 785 ± 13 μs 780 ± 13 μs 1.01 ± 0.046
nonlinearoperators/SoftPlus/jacobian-adjoint 321 ± 12 μs 324 ± 10 μs 0.988 ± 0.096
nonlinearoperators/Tanh/forward 287 ± 4.8 μs 284 ± 5.5 μs 1.01 ± 0.052
nonlinearoperators/Tanh/jacobian-adjoint 240 ± 5.1 μs 232 ± 4.9 μs 1.04 ± 0.062
normaloperators/DFT/mul 7.3 ± 0.58 μs 7.54 ± 0.14 μs 0.969 ± 0.16
normaloperators/DiagOp/mul 668 ± 19 μs 646 ± 14 μs 1.03 ± 0.074
normaloperators/NFFTOp/mul 163 ± 6.9 μs 161 ± 7.6 μs 1.01 ± 0.13
waveletoperators/WaveletOp/adjoint 2.9 ± 0.073 ms 2.94 ± 0.1 ms 0.986 ± 0.083
waveletoperators/WaveletOp/forward 1.39 ± 0.025 ms 1.68 ± 0.039 ms 0.831 ± 0.049
Memory benchmarks
Benchmark base head Ratio (base/head)
batching/SimpleBatchOp/adjoint-single 768 allocs (277.00 KiB) 768 allocs (277.00 KiB) 1
batching/SimpleBatchOp/forward-single 384 allocs (265.00 KiB) 384 allocs (265.00 KiB) 1
batching/SpreadingBatchOp/adjoint-single 418 allocs (140.09 KiB) 418 allocs (140.09 KiB) 1
batching/SpreadingBatchOp/forward-single 224 allocs (134.00 KiB) 224 allocs (134.00 KiB) 1
calculus/AffineAdd/adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/AffineAdd/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/Ax_mul_Bx/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/Ax_mul_Bx/jacobian-adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/Ax_mul_Bxt/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/Ax_mul_Bxt/jacobian-adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/Axt_mul_Bx/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/Axt_mul_Bx/jacobian-adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/BroadCast/identity-single 1 allocs (48 bytes) 1 allocs (48 bytes) 1
calculus/BroadCast/operator-single-adjoint 31 allocs (1.08 KiB) 31 allocs (1.08 KiB) 1
calculus/BroadCast/operator-single-forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/Compose/adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/Compose/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/DCAT/adjoint 1 allocs (32 bytes) 1 allocs (32 bytes) 1
calculus/DCAT/forward 1 allocs (32 bytes) 1 allocs (32 bytes) 1
calculus/HCAT/adjoint 131 allocs (4.70 KiB) 131 allocs (4.70 KiB) 1
calculus/HCAT/forward 70 allocs (2.52 KiB) 70 allocs (2.52 KiB) 1
calculus/HadamardProd/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/HadamardProd/jacobian-adjoint 6 allocs (512.14 KiB) 6 allocs (512.14 KiB) 1
calculus/Jacobian/sigmoid-adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/Reshape/adjoint 1 allocs (32 bytes) 1 allocs (32 bytes) 1
calculus/Reshape/forward 1 allocs (32 bytes) 1 allocs (32 bytes) 1
calculus/Scale/adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/Scale/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/Sum/adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/Sum/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
calculus/VCAT/adjoint 130 allocs (4.67 KiB) 130 allocs (4.67 KiB) 1
calculus/VCAT/forward 71 allocs (2.55 KiB) 71 allocs (2.55 KiB) 1
dspoperators/Filt/adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
dspoperators/Filt/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
dspoperators/MIMOFilt/adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
dspoperators/MIMOFilt/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
dspoperators/Xcorr/adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
dspoperators/Xcorr/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
fftwoperators/DFT/adjoint 45 allocs (258.34 KiB) 45 allocs (258.34 KiB) 1
fftwoperators/DFT/forward 45 allocs (258.34 KiB) 45 allocs (258.34 KiB) 1
linearoperators/DiagOp/adjoint-single 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/DiagOp/adjoint-threaded 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/DiagOp/forward-single 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/DiagOp/forward-threaded 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/Eye/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/FiniteDiff/adjoint 12 allocs (4.00 MiB) 12 allocs (4.00 MiB) 1
linearoperators/FiniteDiff/forward 6 allocs (4.00 MiB) 6 allocs (4.00 MiB) 1
linearoperators/GetIndex/adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/GetIndex/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/LBFGS/mul 65 allocs (1.33 KiB) 65 allocs (1.33 KiB) 1
linearoperators/LBFGS/update 3 allocs (48 bytes) 3 allocs (48 bytes) 1
linearoperators/LMatrixOp/adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/LMatrixOp/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/MatrixOp/adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/MatrixOp/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/MyLinOp/adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/MyLinOp/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/Variation/adjoint-single 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/Variation/forward-single 512 allocs (16.00 KiB) 512 allocs (16.00 KiB) 1
linearoperators/ZeroPad/adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/ZeroPad/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
linearoperators/Zeros/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nfftoperators/NFFTOp/adjoint 152 allocs (5.28 KiB) 152 allocs (5.28 KiB) 1
nfftoperators/NFFTOp/forward 149 allocs (5.17 KiB) 149 allocs (5.17 KiB) 1
nonlinearoperators/Atan/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/Atan/jacobian-adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/Cos/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/Cos/jacobian-adjoint 6 allocs (512.14 KiB) 6 allocs (512.14 KiB) 1
nonlinearoperators/Exp/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/Exp/jacobian-adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/Pow/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/Pow/jacobian-adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/Sech/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/Sech/jacobian-adjoint 6 allocs (512.14 KiB) 6 allocs (512.14 KiB) 1
nonlinearoperators/Sigmoid/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/Sigmoid/jacobian-adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/Sin/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/Sin/jacobian-adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/SoftMax/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/SoftMax/jacobian-adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/SoftPlus/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/SoftPlus/jacobian-adjoint 3 allocs (512.07 KiB) 3 allocs (512.07 KiB) 1
nonlinearoperators/Tanh/forward 0 allocs (0 bytes) 0 allocs (0 bytes) 1
nonlinearoperators/Tanh/jacobian-adjoint 0 allocs (0 bytes) 0 allocs (0 bytes) 1
normaloperators/DFT/mul 0 allocs (0 bytes) 0 allocs (0 bytes) 1
normaloperators/DiagOp/mul 0 allocs (0 bytes) 0 allocs (0 bytes) 1
normaloperators/NFFTOp/mul 7 allocs (208 bytes) 7 allocs (208 bytes) 1
waveletoperators/WaveletOp/adjoint 9 allocs (512.34 KiB) 9 allocs (512.34 KiB) 1
waveletoperators/WaveletOp/forward 9 allocs (512.34 KiB) 9 allocs (512.34 KiB) 1

Ratio interpretation: values > 1 mean the PR is faster; values < 1 mean slower.
🚀 significant speedup · 🐢 significant slowdown

It requires Julia >= 1.11 and is already added dynamically at runtime
for that case in test/utils.jl; listing it statically forced dependency
resolution to fail on the Julia 1.10 LTS CI job.
JLArray satisfies StridedArray/DenseArray, so AbstractFFTs.plan_fft
dispatches to FFTW's raw-pointer CPU plan instead of a GPU-safe path,
and JLArrays intentionally throws on the resulting unsafe_convert to
Ptr ("Illegal conversion of a JLArray to a Ptr"). This broke the
DFT/RDFT/IRDFT, Conv, Xcorr, Filt, and MIMOFilt GPU testitems, which
were missing the include_jlarrays = false guard that the neighboring
DCT/IDCT (GPU) testitem already uses for the same reason.
@codecov

codecov Bot commented Aug 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.13%. Comparing base (861af22) to head (f4d251a).

Additional details and impacted files
@@            Coverage Diff             @@
##           master      #43      +/-   ##
==========================================
+ Coverage   87.13%   90.13%   +2.99%     
==========================================
  Files          51       51              
  Lines        3716     3679      -37     
==========================================
+ Hits         3238     3316      +78     
+ Misses        478      363     -115     

☔ 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.

hakkelt and others added 6 commits August 12, 2026 00:11
…ratorWrapper

These types had no direct test of the storage_type/threaded deep-copy
path added by copy_operator's refactor, so the codecov patch-coverage
gate flagged their _copy_operator_impl methods as untested. Also adds
a direct test of copy_operator's fast-path/slow-path dispatch and the
default (deepcopy) fallback.

Each new test forces the deep-copy path with an explicit non-default
kwarg, since the fast path (thread-safe operator, no kwargs) just
returns the same operator unchanged. Manually verified against the
package (TestItemRunner/GPUEnv itself hit an unrelated local Pkg.jl
manifest bug, JuliaLang/Pkg.jl#4086, on this sandbox).
Julia's === for immutable structs can compare egal by field content
rather than allocation identity, and this differs across Julia
versions: the Variation test's !== assertion passed on 1.12 locally
but failed on the 1.10 LTS CI job because the copied Variation ended
up field-identical to the original. Removed the same fragile pattern
from the other new copy_operator tests (Sum, BroadCast, OperatorWrapper,
the MatrixOp fast/slow-path test) and kept only the functional (mul!)
equivalence and isa checks, matching the already-stable HadamardProd
test's style. DiagOp's op3.d !== op.d assertion is unaffected since it
compares two Array objects directly, not immutable operator structs.
…cing_expr

Both were still flagged as uncovered by codecov's patch-coverage gate
despite being exercised by existing tests, so add more direct tests:
an explicit threaded=true call for HadamardProd's _copy_operator_impl,
and a 3-element HCAT to unambiguously exercise the get_slicing_expr
loop body across multiple iterations.
Root AGENTS.md carried directory-layout and generic Julia perf advice
a session can already derive, plus two large sections that only matter
in specific contexts. Move GPU extension conventions to
ext/GpuExt/AGENTS.md (loads only when working in that directory) and
the long-running test/coverage/benchmark workflow to a skill, keeping
CLAUDE.md as a symlink to AGENTS.md per repo convention.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JHYpJyvm5XwhtMXLE1N8i9
Add copy_operator tests for HCAT and HadamardProdJac, and a test for the
generic domain/codomain_array_type fallback (_storage_type_for_elem with a
Tuple), closing the coverage gaps flagged in the PR kul-optec#43 Codecov patch report.

Writing the HadamardProdJac test surfaced a real bug: its
_copy_operator_impl used _convert_buffer (shape-only, no value copy) on
bufA/bufB, which hold the Jacobian's linearization point (A*x, B*x) carried
over from the originating HadamardProd rather than pure scratch. Copying
wiped that state, producing garbage adjoints. Fixed by copying bufA/bufB
with copy/copyto! (preserving values, still honoring storage_type
conversion), leaving bufD on the fast path since it's pure scratch.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JHYpJyvm5XwhtMXLE1N8i9
@hakkelt
hakkelt marked this pull request as ready for review August 14, 2026 08:35
@hakkelt

hakkelt commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator Author

@lostella this PR is ready to review. It contains no significant changes, just minor enhancements and fixes, and a lot of new tests.

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