Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .github/workflows/rust-host.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

name: Rust host checks

on:
push:
branches:
- main
- "pull-request/[0-9]+"
paths:
- "rust/**"
- ".github/workflows/rust-host.yml"
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
host:
runs-on: ubuntu-latest
defaults:
run:
working-directory: rust
shell: bash --noprofile --norc -euo pipefail {0}
env:
RUSTDOCFLAGS: -D warnings
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- name: Check the pinned Rust workspace
run: |
rustup toolchain install --no-self-update
rustup show active-toolchain
cargo fmt --all -- --check
cargo test --workspace --locked
cargo clippy --workspace --all-targets --locked -- -D warnings
cargo doc --workspace --no-deps --locked
3 changes: 3 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ CUDA Core Compute Libraries

cccl/index
python/index
rust/index
contributors/index
maintainers/index
infrastructure/index
Expand All @@ -18,6 +19,8 @@ make CUDA C++ and Python more delightful.

- :doc:`Python Libraries <python/index>`

- :doc:`Rust Development <rust/index>`

- :doc:`Contributor Docs <contributors/index>`

- :doc:`Maintainer Docs <maintainers/index>`
Expand Down
119 changes: 119 additions & 0 deletions docs/rust/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
.. Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
.. SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

Rust development
================

The Rust workspace contains the native host compiler foundation for ``cuda.coop``.
Its private ``cuda-coop-codegen`` crate specializes CUB block operations and returns
linkable device LTO-IR with exact temporary-storage requirements. It supports
compiler integration development; an application-facing Rust device API is still
under development. The crate is unpublished and its interface can change.

The workspace is separate from CCCL's CMake build. Building the existing C++
libraries does not require Rust, and the provider does not depend on Python.

Supported provider forms
------------------------

Each request describes a complete, one-dimensional block, an ``i32`` payload,
a positive compile-time item count per thread, and one of these forms:

.. list-table::
:header-rows: 1
:widths: 25 45 30

* - Operation
- Behavior
- Payload requirement
* - Full Load
- Fills every payload slot in blocked order
- Writable storage
* - Default-filled Load
- Loads a valid prefix and fills the suffix with a supplied value
- Writable storage
* - Full Store
- Writes every payload slot to memory
- Every slot initialized
* - Partial Store
- Writes a valid prefix; leaves the destination suffix unchanged
- Every slot initialized

Both Direct and Transpose algorithms are supported. Direct accesses no shared
scratch. Transpose Store redistributes blocked payloads across lanes into striped
order, retaining initialized values in every slot, and uses the exact CUB storage
layout. Compiler integrations must enforce collective participation, memory
ownership, valid bounds, and synchronization before scratch reuse. Full and
masked Load produce fully initialized payloads; no-default masked Load is outside
this provider's current scope.

Compile a provider
------------------

Use the pinned toolchain in ``rust/rust-toolchain.toml``. Host tests, lint checks,
and rustdoc builds need no CUDA installation. Running native compilation requires
a Linux CUDA toolkit with NVRTC LTO support; CUDA 13.3 is the initial validation
toolkit. A GPU and CUDA context are not required.

From the CCCL checkout:

.. code-block:: shell

cd rust
cargo test --workspace
cargo clippy --workspace --all-targets -- -D warnings
RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps
cargo run -p cuda-coop-codegen --example specialize -- \
/usr/local/cuda-13.3 compute_120 /tmp/block_load.ltoir

The example below is the executed Cargo source. It obtains its CCCL source root
from its build location, passes an explicit toolkit root, compiles a filled Load,
and writes the resulting LTO-IR. It does not link or launch a device kernel.

.. literalinclude:: ../../rust/cuda-coop-codegen/examples/specialize.rs
:language: rust
:start-after: //! Compile a host-side provider without a CUDA context or a device consumer.

Native regression checks are opt-in:

.. code-block:: shell

CUDA_HOME=/usr/local/cuda-13.3 cargo test --workspace -- --include-ignored

``CUDA_COOP_TEST_TARGET`` can select another supported NVRTC target; its default
is ``compute_120``. These checks compile the supported Direct/Transpose forms at
item counts 1 and 4, compare repeated LTO output, and check exact layout decoding
and specialization identity. They do not execute GPU kernels.

Compiler integration and API reference
--------------------------------------

``Provider::from_checkout`` snapshots headers from the explicitly selected CCCL
checkout and toolkit, then loads NVRTC from that toolkit's ``lib64`` directory.
Those native libraries are trusted executable compiler inputs. No Python wheel,
working-directory header lookup, or runtime query kernel is involved. Reuse the
provider and batch requests for a common target into one NVRTC compilation.

The same NVRTC program produces both LTO-IR and each CUB ``TempStorage`` layout.
The result distinguishes scratch-free specializations from an empty C++ type's
nonzero ``sizeof``. Input identities include the request, header contents,
provider source, loaded NVRTC/builtins bytes, version, target, and compiler options.
Symbols include a specialization digest. Request planning must assign each
specialization to exactly one batch per final link: a batch is one indivisible
LTO-IR buffer, so partially overlapping batches would duplicate strong definitions.

Rustdoc is the API reference, including the generated ABI's pointer, validity,
mutation, and collective requirements. Open ``rust/target/doc/cuda_coop_codegen/index.html``
after the documentation command above, or run ``cargo doc --no-deps --open`` from
``rust/``. Device discovery, lowering, linking, launch enforcement, and Cargo
invalidation of external compiler inputs belong to the compiler integration.

The Oxide adapter's ``oxide::serve_inputs`` answers
``--oxide-library-inputs-v1`` with the selected header roots and NVRTC library
paths, without loading CUDA. A provider build script dispatches this query
alongside ``--oxide-library-request-v1``. Device registration getters use
``cuda_device::library::registration!("REGISTRATION_ENV_NAME")`` so the frontend
tracks those files, directory contents and selected toolkit before emitting
Cargo dependency information. Host checks and rustdoc do not query CUDA inputs.
Cargo's timestamp freshness rules apply; replacements with unchanged or older
timestamps may require an explicit rebuild.
1 change: 1 addition & 0 deletions rust/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/target/
63 changes: 63 additions & 0 deletions rust/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Rust `cuda.coop` guidance

Read the repository's root guidance first. Apply this file to the Rust
workspace, its examples and tests, and `docs/rust/`.

## Design tenets

The design tenets of `cuda.coop` are **performant, consistent, delightful**.

- **Performant:** target negligible overhead over CUB through compile-time
planning, inlining and LTO. Avoid hidden runtime work. Inspect the final
device artifact and measure representative execution before making claims
about register use, spills or overhead.
- **Consistent:** preserve common operation names, group-first arguments,
defaults, CUB behavior, mutation and result ownership. Document necessary
Rust syntax and safety adaptations. Additional capabilities extend shared
behavior without changing it.
- **Delightful:** use idiomatic Rust, useful defaults, inferred element types,
reusable generic kernels, ordinary Cargo builds and actionable errors.

## API and examples

- Use the single `cuda_coop` API, normally with `use cuda_coop as coop;`.
State the supported Oxide compiler/toolchain explicitly. Do not duplicate
primitive namespaces to separate built-in operators from static callables.
- Make the main per-thread item count a kernel const generic named
`ITEMS_PER_THREAD`, propagated through helpers and host specialization.
Keep operation-specific auxiliary and output extents independent.
- Infer payload element types from typed producers or assignments while
preserving widths. Investigate inference failures instead of adding a
redundant element type to an ordinary example. Document full signatures.
- Load fills its payload in place and returns unit. Preserve fresh results
where the common operation requires them, and reflect Store mutation in
borrowing and validity. Undefined, partial and root-only results must not
become unrestricted initialized Rust values.
- Preserve hierarchy units, supported groups, storage sharing and explicit
synchronization obligations. A group descriptor or Rust borrow alone is
not a proof of collective participation or shared-memory safety.
- Required collective completion must not depend solely on `Drop` running.

## Ownership and validation

Keep CUB specialization, exact scratch layout queries and operation semantics
in the native host provider. Keep compiler discovery, lowering, allocation,
device linking and launch enforcement in Oxide. Host compiler libraries and
filesystem dependencies must stay out of device code. CMake consumers do not
acquire a Rust requirement.

Every public item needs useful rustdoc: arguments and generic parameters,
defaults, supported types/groups, participation, layout, mutation and result
validity, scratch/synchronization, errors and examples. Every public unsafe
item needs a concrete `# Safety` contract. Use rustdoc as the API reference
and the CCCL Rust guide for complete programs and explanations.

Prefer end-user primitive tests, with item counts 1 and 4 where supported.
Use focused compiler/provider fixtures for independently reviewable compiler
capabilities. Keep displayed examples and their executed source identical.
Distinguish host tests, rustdoc/doctests, device compilation, GPU execution,
sanitizers and current-head CI. A sanitizer pass is not a Rust soundness proof.

Run formatting, applicable lints, warning-free documentation and meaningful
targeted tests. Correct foundational defects at their owning layer and
requalify dependents instead of hiding a redesign in a later primitive family.
Loading
Loading