Template Metal complex scalar lanes - #2
Draft
PhysicistJohn wants to merge 1 commit into
Draft
Conversation
Replace the float-specific Metal complex struct with complex_t<T> while retaining complex64_t as an alias and preserving existing kernel entry points. Generalize scalar and cross-complex conversions, arithmetic, and limits so half and bfloat lane types retain packed two-lane storage without implicit float promotion.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
MLX Metal currently defines complex storage and arithmetic only through the float-specific
complex64_t, while MLX CUDA already uses the lane-genericcomplex_t<T> = cuda::std::complex<T>. This PR independently gives the Metal backend the same extensible type foundation while preserving all current complex64 behavior and kernel entry points.It complements upstream #3969, which independently templates the Metal C2C FFT scalar lane. Together, the two narrowly scoped changes establish the orthogonal type and FFT foundations needed to evaluate reduced-precision complex support in MLX. That closes a capability gap with accelerator stacks that already provide reduced-precision complex transforms: NVIDIA cuFFT supports FP16 and BF16 complex transforms, and AMD rocFFT supports FP16 complex transforms.
Neither PR introduces a user-facing dtype or commits MLX to promotion, dispatch, or accuracy semantics; those remain separate design decisions.
Summary
complex_t<T>.using complex64_t = complex_t<float>.Limitsfor packed half and bfloat lane types.Scope boundaries
This patch intentionally does not add public complex32/complex16 dtypes, host promotion rules, Python API, production half/BF16 kernel instantiations, FFT integration, or FP8. Those should be separate proposals after this primitive is accepted.
The current Metal compiler accepts the template implementation but rejects C++20
conceptdeclarations, so mixed scalar operators use a narrowenable_ifalias for equivalent compile-time constraints.Compatibility checks
macos-metal2.4, macOS 14.0)The metallib increase is confined to module and reflection metadata. No new public kernel symbols are emitted.
Reduced-lane proof
Both
complex_t<half>andcomplex_t<bfloat16_t>are exactly 4 bytes. A linked on-device probe produced the expected(-2, 14)result for both types.LLVM AIR inspection shows native half and bfloat loads, stores, arithmetic, division, and FMA instructions. The reduced paths do not promote their internal arithmetic to float.
A focused on-device streaming complex multiply-add benchmark over 2^24 elements measured:
This is a raw-type bandwidth-oriented microbenchmark, not an end-to-end MLX dtype performance claim.