Skip to content

[cuda.compute]: reject RawOp values with mismatched complex layout - #11525

Open
saiyambharara wants to merge 1 commit into
NVIDIA:mainfrom
saiyambharara:fix-complex-struct-alignment
Open

saiyambharara wants to merge 1 commit into
NVIDIA:mainfrom
saiyambharara:fix-complex-struct-alignment

Conversation

@saiyambharara

@saiyambharara saiyambharara commented Sep 20, 2026

Copy link
Copy Markdown

Description

closes #11347

cuda.compute builds complex64/complex128 layout in structs and subarrays through NumPy's align=True, which aligns them to their component size instead of libcu++'s alignas(2 * sizeof(T)). A RawOp casting to a native struct can read or write the wrong bytes with no error.

RawOp.compile() now checks input and output types against the native layout, including nested structs, subarrays, and pointers, and raises a clear error instead of building a broken kernel.

Fixing the layout itself is bigger separate work: NumPy's packer can't use a different alignment per field, and the MLIR/LLVM codegen for Python callable operators would also need to agree. Those operators aren't affected by this bug either way, since numba-cuda-mlir represents complex values consistently on its own.

Testing

New test_raw_op_complex_layout.py (18 tests), plus test_raw_op.py, test_no_numba.py, test_select.py, test_struct_conversions.py, test_nested_struct.py, and test_struct_field_validation.py all pass.

Checklist

  • New or existing tests cover these changes.
  • The documentation is up to date with these changes.

cc @NaderAlAwar for review, and @shwina @Jacobfaib @oleksandr-pavlyk for visibility.

@copy-pr-bot

copy-pr-bot Bot commented Sep 20, 2026

Copy link
Copy Markdown
Contributor

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@cccl-authenticator-app cccl-authenticator-app Bot moved this from Todo to In Progress in CCCL Sep 20, 2026
@saiyambharara saiyambharara changed the title cuda.compute: reject RawOp values with mismatched complex layout [cuda.compute]: reject RawOp values with mismatched complex layout Sep 20, 2026
NumPy's align=True packer aligns complex64 and complex128 to their
real component instead of libcu++'s alignas(2 * sizeof(T)). A RawOp
casting to a native struct can silently read or write the wrong
bytes when a complex field lands at a different offset (NVIDIA#11347).

RawOp.compile() now checks input and output layouts against native
CUDA/C++, including nested structs, subarrays, and pointers, and
raises a clear error instead of building a broken kernel.

Python callable operators are not affected.
@saiyambharara
saiyambharara force-pushed the fix-complex-struct-alignment branch from ab96be6 to 2bdbfe2 Compare September 20, 2026 21:24
@saiyambharara
saiyambharara marked this pull request as ready for review September 20, 2026 21:25
@saiyambharara
saiyambharara requested a review from a team as a code owner September 20, 2026 21:25
@cccl-authenticator-app cccl-authenticator-app Bot moved this from In Progress to In Review in CCCL Sep 20, 2026
@coderabbitai

coderabbitai Bot commented Sep 20, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

📝 Summary

Summary by CodeRabbit

  • Bug Fixes
    • Added validation to detect mismatched CUDA type layouts before operations are compiled.
    • Improved handling of complex types, nested structures, pointers, subarrays, field offsets, size, and alignment.
    • Prevented invalid operations from compiling and producing incorrect results.
    • Preserved support for Python-callable operators.

Walkthrough

RawOp compilation now validates CUDA type-descriptor layouts against native CUDA/C++ layouts. The validation covers complex types, nested structs, pointers, subarrays, offsets, size, and alignment. Regression tests cover rejection, compatibility, and end-to-end execution.

Changes

RawOp layout validation

Layer / File(s) Summary
Native layout computation and recursive validation
python/cuda_cccl/cuda/compute/op.py
The new helpers compute native offsets, sizes, and alignments and compare them with CUDA type descriptors. Mismatches raise TypeError.
RawOp compilation integration
python/cuda_cccl/cuda/compute/op.py
RawOp.compile validates input and output descriptors before constructing the operation. Python-callable operators are not subject to this validation.
Complex layout regression coverage
python/cuda_cccl/tests/compute/test_raw_op_complex_layout.py
Tests cover nested structs, pointers, fixed-size subarrays, alignment mismatches, coincidental compatibility, and end-to-end LTO execution.

Assessment against linked issues

Objective Addressed Explanation
Match native cuda::std::complex layouts or reject incompatible RawOp layouts [#11347]

Suggested reviewers: shwina

Priority: ➖ Normal

Change: Bug fix · Severity of issue fixed: Medium


Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

🧹 Nitpick comments (1)
python/cuda_cccl/cuda/compute/op.py (1)

68-71: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

suggestion: checking a pointee as a root rejects valid programs when the pointee is a scalar. Example: a struct field of type complex64*. _check_raw_op_layout then reaches the bare-type branch and compares NumPy's 4-byte alignment with the native 8, so compilation fails. No byte layout differs in that case: the element size is identical, and the pointed-to allocation is not laid out by cuda.compute. Restrict the pointee check to struct pointees, where field offsets and stride can actually disagree.

     if isinstance(td, cccl_types.PointerTypeDescriptor):
         # The pointee is a separate allocation: check it as its own root.
-        _check_raw_op_layout(td.pointee, path=f"*{path}")
+        # Only its internal layout can disagree; a scalar pointee's alignment
+        # is a property of the allocation, not of the layout.
+        if isinstance(td.pointee, cccl_types.StructTypeDescriptor):
+            _check_raw_op_layout(td.pointee, path=f"*{path}")
         return

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: NVIDIA/cccl/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 7a3eb549-236e-444b-9e09-ed30d8925c9a

📥 Commits

Reviewing files that changed from the base of the PR and between 48414ba and 2bdbfe2.

📒 Files selected for processing (2)
  • python/cuda_cccl/cuda/compute/op.py
  • python/cuda_cccl/tests/compute/test_raw_op_complex_layout.py

Included review availability: Your plan provides up to 12 included reviews per hour; 11 remain after this review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Review

Development

Successfully merging this pull request may close these issues.

[BUG]: cuda.compute: struct and ZipIterator layouts built from complex dtypes use numpy host alignment instead of cuda::std::complex device alignment

1 participant