Skip to content

[STF] Expose geometry-aware allocation and native partition functions in the C API#10038

Merged
caugonnet merged 8 commits into
NVIDIA:mainfrom
caugonnet:stf-c-allocate-nd
Jul 21, 2026
Merged

[STF] Expose geometry-aware allocation and native partition functions in the C API#10038
caugonnet merged 8 commits into
NVIDIA:mainfrom
caugonnet:stf-c-allocate-nd

Conversation

@caugonnet

Copy link
Copy Markdown
Contributor

Description

Make composite data places usable end to end from the C API:

  • stf_partition_fn_blocked(dim) / stf_partition_fn_cyclic() expose the existing blocked/cyclic partitioners as native stf_get_executor_fn values, so C callers can build composite data places (stf_data_place_composite(), already on main) without hand-writing an FFI callback for the standard mappings.
  • stf_data_place_allocate_nd(dims, elemsize) forwards to the C++ data_place::allocate_nd already on main: equivalent to a byte-count allocation on ordinary places, geometry-aware block placement on composite ones — where the plain byte-count stf_data_place_allocate correctly fails, since a byte count alone cannot carry the tensor geometry.

Both additions only use types already present in the C API (stf_dim4, stf_get_executor_fn). Nothing here depends on structured (cute) partitions; those, together with placement evaluation and the Python bindings, remain in #9892, which this PR is split out of so it can target main directly instead of being stacked on #5315.

Tested with a new test_allocate_nd.cpp: shaped allocation on an ordinary device place, clean byte-count failure plus successful allocate_nd on composite places built with both native partition functions, with device round-trip verification.

Checklist

  • I am familiar with the Contributing Guidelines.
  • New or existing tests cover these changes.
  • The documentation is up to date with these changes.

🤖 Generated with Claude Code

… in the C API

Make composite data places usable end to end from C:

- stf_partition_fn_blocked(dim) / stf_partition_fn_cyclic() expose the
  existing blocked/cyclic partitioners as native stf_get_executor_fn
  values, so composite places can be built without FFI callback cost.
- stf_data_place_allocate_nd(dims, elemsize) forwards to the C++
  data_place::allocate_nd already on main: equivalent to a byte-count
  allocation on ordinary places, geometry-aware block placement on
  composite ones (where the plain byte-count stf_data_place_allocate
  correctly fails, since a byte count alone cannot carry the geometry).

Both additions only use types already in the C API (stf_dim4,
stf_get_executor_fn); nothing here depends on structured (cute)
partitions, which remain in a separate PR.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@caugonnet
caugonnet requested a review from a team as a code owner July 21, 2026 07:47
@caugonnet
caugonnet requested a review from NaderAlAwar July 21, 2026 07:47
@github-project-automation github-project-automation Bot moved this to Todo in CCCL Jul 21, 2026
@copy-pr-bot

copy-pr-bot Bot commented Jul 21, 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 Review in CCCL Jul 21, 2026
@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Changes

The STF C API adds blocked and cyclic partition helpers and tensor-aware ND allocation. Implementations validate shaped allocation inputs and blocked partition geometry, while tests cover ordinary and composite placements, partition dimensions, device round trips, and overflow rejection.

Suggested reviewers: andralex


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.

Actionable comments posted: 3


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 76d91229-5f74-42e1-9656-f1dc8323c749

📥 Commits

Reviewing files that changed from the base of the PR and between 56f4f6a and 1dc2030.

📒 Files selected for processing (3)
  • c/experimental/stf/include/cccl/c/experimental/stf/stf.h
  • c/experimental/stf/src/stf.cu
  • c/experimental/stf/test/test_allocate_nd.cpp

Comment thread c/experimental/stf/test/test_allocate_nd.cpp Outdated
Comment thread c/experimental/stf/test/test_allocate_nd.cpp Outdated
Comment thread c/experimental/stf/test/test_allocate_nd.cpp Outdated
caugonnet and others added 2 commits July 21, 2026 09:57
- Rename MiB to one_mib (snake_case per coding guidelines).
- Declare immutable locals const throughout.
- Cover every blocked dimension selector (0-3) and out-of-range values
  (-1, 4) with a 4D shape divisible by the grid along each axis.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 9418e47f-0cb0-4642-992e-34f81a1a9095

📥 Commits

Reviewing files that changed from the base of the PR and between 1dc2030 and 859e6c6.

📒 Files selected for processing (1)
  • c/experimental/stf/test/test_allocate_nd.cpp

Comment thread c/experimental/stf/test/test_allocate_nd.cpp Outdated
Compile-time test constants (one_mib, shapes, element counts) are now
constexpr, with the namespace-scope constant inline constexpr.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@caugonnet

Copy link
Copy Markdown
Contributor Author

/ok to test 66a3a03

@caugonnet
caugonnet enabled auto-merge (squash) July 21, 2026 08:16
@github-actions

This comment has been minimized.

::std::memcpy(&dims, data_dims, sizeof(dims));
try
{
return from_opaque(h)->allocate_nd(dims, elemsize, stream);

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.

Important: Validate the extent and byte-count multiplications before forwarding. With dims={UINT64_MAX, UINT64_MAX, 1, 1} and elemsize=1, dim4::size() wraps to 1: an ordinary place returns a non-null one-byte allocation, while a two-place blocked composite terminates with SIGFPE after the mapper computes a zero part_size. The try/catch cannot catch this. Please checked-multiply all extents and elemsize, return nullptr on overflow, and add regression coverage for both paths.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 8f38c13. data_place::allocate_nd() now checked-multiplies all four extents and elemsize, rejecting geometries whose byte count overflows size_t or exceeds PTRDIFF_MAX (std::invalid_argument, surfaced as NULL through the C API). The check sits at the single entry point, before any partitioner math runs, so both paths you describe are covered: the ordinary place no longer silently returns a wrapped (tiny) allocation, and the composite blocked place can no longer reach the part_size == 0 division (the SIGFPE). blocked_partition::get_executor additionally asserts nplaces > 0 and part_size > 0 to document the precondition. Regression coverage added on both paths, in C (test_allocate_nd.cpp, "shaped allocation rejects overflowing geometries": extent wrap, elemsize wrap, above-PTRDIFF_MAX, and the composite case that used to SIGFPE) and C++ (placement.cu, test_shaped_alloc_overflow).

Comment on lines +287 to +290
//! \brief Native blocked partition function for a given dimension
//! (values outside [0, 3] select the highest-rank dimension, like -1),
//! usable wherever an stf_get_executor_fn is expected without any FFI
//! callback cost.

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.

Suggestion: document the clamping behavior to the highest axis whose extent is greater than one

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 8f38c13. The doc now states that the requested dimension is clamped to the highest axis whose extent is greater than one — including the case where an in-range dim beyond that axis is clamped down (e.g. dim 2 on extents {n, 1, 1, 1} partitions along axis 0). The same clarification was added to the blocked_partition doc block in the C++ header.

…locked-partition clamping

Address review feedback on NVIDIA#10038:

- data_place::allocate_nd() now checked-multiplies the extents and
  element size, rejecting geometries whose byte count overflows size_t
  or exceeds PTRDIFF_MAX (std::invalid_argument, surfaced as NULL
  through the C API). Previously the product silently wrapped: an
  ordinary place returned a tiny allocation for an astronomically
  large tensor, and a composite blocked place died with SIGFPE on a
  zero part_size.
- Assert the (now guaranteed) preconditions in
  blocked_partition::get_executor instead of dividing by zero.
- Document that the blocked partition dimension is clamped to the
  highest axis whose extent is greater than one, including for
  in-range dimension selectors.
- Add regression tests on both the C and C++ paths.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@caugonnet
caugonnet requested a review from a team as a code owner July 21, 2026 14:10
@caugonnet
caugonnet requested a review from andralex July 21, 2026 14:10

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
cudax/include/cuda/experimental/__places/partitions/blocked_partition.cuh (1)

117-118: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

suggestion: nplaces is never reassigned after line 117; declare it const. As per coding guidelines, "All variables that are not modified must be declared const, including cast results, function return values, and loop-invariant computations."

♻️ Proposed fix
-    size_t nplaces = grid_dims.x;
+    const size_t nplaces = grid_dims.x;

Source: Coding guidelines

cudax/test/places/placement.cu (1)

272-282: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

suggestion: dev, grid, and c are never reassigned after initialization; declare them const. As per coding guidelines, "All variables that are not modified must be declared const, including cast results, function return values, and loop-invariant computations."

♻️ Proposed fix
-  data_place dev = data_place::device(0);
+  const data_place dev = data_place::device(0);
   expect_invalid(dev, wrapping_dims, 1);
   ...
-  auto grid    = make_device_grid(ndevs, 2);
-  data_place c = data_place::composite(blocked_partition_custom<1>{}, grid);
+  const auto grid    = make_device_grid(ndevs, 2);
+  const data_place c = data_place::composite(blocked_partition_custom<1>{}, grid);

Source: Coding guidelines


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: d934ecbb-8252-4e46-ab0b-b12fa2d9b173

📥 Commits

Reviewing files that changed from the base of the PR and between 66a3a03 and 8f38c13.

📒 Files selected for processing (5)
  • c/experimental/stf/include/cccl/c/experimental/stf/stf.h
  • c/experimental/stf/test/test_allocate_nd.cpp
  • cudax/include/cuda/experimental/__places/partitions/blocked_partition.cuh
  • cudax/include/cuda/experimental/__places/places.cuh
  • cudax/test/places/placement.cu
🚧 Files skipped from review as they are similar to previous changes (1)
  • c/experimental/stf/include/cccl/c/experimental/stf/stf.h

Comment thread cudax/test/places/placement.cu
caugonnet and others added 2 commits July 21, 2026 16:20
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@caugonnet

Copy link
Copy Markdown
Contributor Author

/ok to test 97b06e4

@github-actions

Copy link
Copy Markdown
Contributor

🥳 CI Workflow Results

🟩 Finished in 1h 30m: Pass: 100%/61 | Total: 1d 18h | Max: 1h 29m | Hits: 6%/317954

See results here.

@caugonnet
caugonnet merged commit c27dc9d into NVIDIA:main Jul 21, 2026
81 of 82 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

3 participants