@csvance Very good to see Julia shine in deep learning tasks, excellent work!
Since in the blog post you focus on CNNs+Neural ODEs, I was wondering what is your assessment of Lux + Reactant’s performance on more standard architectures.
Lately, I have been landing a lot of optimizations in Flux.jl and its ecosystem (Zygote.jl, NNlib.jl, MLUtils.jl, HuggingFaceDatasets.jl, HuggingFaceTokenizers.jl) and filed tons of issues to CUDA.jl, Enzyme.jl, and Reactant.jl (whose maintainers I thank a lot, they have been very helpful and responsive). So far, I am very satisfied with the improvements on non-reactant backends, slightly less so with Reactant.
For instance, in Refresh ResNet and GPT-2 examples and benchmarks - Pull Request #2794 - FluxML/Flux.jl - GitHub I benchmarked two standard training examples, a vision one (ResNet18 trained on Tiny ImageNet) and a language one (GPT-2 trained on FineWeb, similar to Karpathy’s nanogpt).
Training measurements on an RTX 5090 (higher is better):
| Example |
Flux + CUDA |
Flux + Reactant |
PyTorch |
PyTorch compiled |
| ResNet, images/s |
2,830 |
3,270 |
3,450 |
3,950 |
| GPT-2, tokens/s |
167k |
131k |
158k |
163k |
So for GPT-2, Flux + CUDA (+ Zygote) is on par with PyTorch, even slightly better,
while Reactant lags behind, most likely due to a missing fused/flash attention StableHLO operator, which forces reactant to materialize attention weights Fused (flash) attention for NNlib.scaled_dot_product_attention under tracing · Issue #3510 · EnzymeAD/Reactant.jl · GitHub
On the vision task instead, Reactant performs slightly better than Flux + CUDA, but still lags behind eage and compiled pytorch. It is likely that the gap between Flux + CUDA and eager pytorch will mostly fixed once cuDNN: add measured convolution plan selection for fixed-shape workloads · Issue #3506 · JuliaGPU/CUDA.jl · GitHub is resolved. I wouldn’t know how to improve Reactant’s performance though. Maybe Reactant: pipeline batch prefetch, transfers, and loss readback · Issue #2801 · FluxML/Flux.jl · GitHub (which I filed after reading your blog post) could help, but I don’t think it will be enough to match pytorch compiled, let’s see.
I would be curious to see the Lux (+ ReactantNitro.jl?) port of those examples, especially if done by you, since I could be missing something.