Skip to content

Drop DLPack dependency; reorganize examples as perf benchmarks#67

Merged
CarloLucibello merged 1 commit into
mainfrom
cl/drop-dlpack-perf-examples
Jul 7, 2026
Merged

Drop DLPack dependency; reorganize examples as perf benchmarks#67
CarloLucibello merged 1 commit into
mainfrom
cl/drop-dlpack-perf-examples

Conversation

@CarloLucibello

Copy link
Copy Markdown
Collaborator

Summary

Two independent, docs-heavy changes bundled together:

1. Drop the DLPack.jl dependency

numpy2jl no longer routes through DLPack. Instead it wraps the numpy buffer as a genuine Array via a vendored PyArray + unsafe_wrap, rooted through a module-level WeakKeyDict (weak key = the wrapper Array, strong value = the PyArray) so the Python buffer stays alive exactly as long as the Julia array and is released when it's GC'd.

  • Same behavior & performance as DLPack: the result is <: DenseArray, so BLAS/GPU/fast-indexing paths are preserved (a bare PyArray misses all of these). Axis reversal and the read-only / non-contiguous copy guards are kept.
  • Bonus deadlock fix: PythonCall's GIL-deferred decref means a finalizer firing on a parallel=true worker thread enqueues the pointer rather than re-acquiring the GIL — so the thread-finalizer deadlock that DLPack's eager-decref finalizer could cause is gone.
  • Removes the unmaintained DLPack dep from Project.toml and the using DLPack import.

2. Reorganize the Flux examples as perf/ benchmarks

  • Move examples/flux_mnist and examples/flux_cifar10 under perf/ (alongside perf/load_dataset/) and delete the now-empty examples/. All doc/README path references updated.
  • Add a 2-worker Distributed row to every benchmark config, run the Julia loaders at -t4 (was -t8), and make the PyTorch scripts read EPOCHS from the env.
  • Refresh both READMEs with fresh 10-epoch numbers (Ryzen Threadripper PRO 9955WX CPU / RTX 5090 GPU). The longer runs give clean, monotonic worker-scaling curves.
  • Fix a stale map(copy, …) note in the MNIST README (the code uses [:]) and align the deadlock framing with the deferred-decref behavior.

Testing

  • Full test suite green (~447 tests), including the 15 serialization tests.
  • Verified no memory leak (WeakKeyDict drains to 0) and no deadlock under parallel finalizers.
  • Ran all four benchmarks end-to-end at 10 epochs (exit 0): MNIST ~98% test acc, CIFAR-10 ~80–83%.

🤖 Generated with Claude Code

Replace the DLPack.jl-based numpy→Julia conversion in `numpy2jl` with a
vendored zero-copy `PyArray` + `unsafe_wrap`, rooted through a `WeakKeyDict`
for lifetime safety. Behavior and performance match DLPack (a genuine
`DenseArray`, so BLAS/GPU fast paths are preserved), and as a bonus the
GIL-finalizer deadlock is gone: PythonCall's deferred decref means a finalizer
firing on a worker thread enqueues the pointer instead of re-acquiring the GIL.
Removes the now-unmaintained DLPack dependency.

Move the Flux MNIST/CIFAR-10 examples under `perf/` alongside `load_dataset/`,
add a 2-worker Distributed row, run the loaders at `-t4`, and refresh both
READMEs with fresh 10-epoch benchmark numbers (Threadripper CPU / RTX 5090
GPU). Update all example path references across the docs and READMEs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@CarloLucibello CarloLucibello merged commit fb8006b into main Jul 7, 2026
9 of 10 checks passed
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