Skip to content
Closed
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
31 changes: 31 additions & 0 deletions .github/workflows/ptx_export.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Export portable PTX

on:
pull_request:
branches: [main, experiment/cuda13.3-llvm21, "stack/**"]
workflow_dispatch:
push:
branches: [poc/portable-ptx-export]

permissions:
contents: read

jobs:
export:
runs-on: ubuntu-24.04
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
- uses: DeterminateSystems/nix-installer-action@main
- name: Compile Rust kernels without a GPU
run: nix develop .#v21 --command cargo run -p ptx_export --features llvm21 -- artifacts/ptx
- name: Record provenance
run: |
git rev-parse HEAD > artifacts/ptx/source-commit.txt
nix develop .#v21 --command rustc -Vv > artifacts/ptx/rustc-version.txt
sha256sum artifacts/ptx/rust_kernels.ptx > artifacts/ptx/SHA256SUMS
- uses: actions/upload-artifact@v4
with:
name: rust-ptx
path: artifacts/ptx/
if-no-files-found: error
15 changes: 15 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ members = [
"examples/sha2_crates_io/kernels",
"examples/vecadd",
"examples/vecadd/kernels",
"examples/ptx_export",
"examples/ptx_export/kernels",

"samples/introduction/async_api",
"samples/introduction/async_api/kernels",
Expand Down
12 changes: 12 additions & 0 deletions examples/ptx_export/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "ptx_export"
version = "0.1.0"
edition = "2024"
publish = false

[features]
default = []
llvm21 = ["cuda_builder/llvm21"]

[dependencies]
cuda_builder = { workspace = true }
16 changes: 16 additions & 0 deletions examples/ptx_export/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Export PTX without a GPU host application

Compile vector-addition and SHA-256 kernels without linking a CUDA host
application or launching a GPU. Compilation requires the Linux Rust-CUDA
toolchain, CUDA toolkit, and NVVM libraries.

```sh
nix develop .#v21 --command cargo run -p ptx_export --features llvm21 -- artifacts/ptx
```

The output is `rust_kernels.ptx`; `final-module.ll` records the NVVM input.
The builder selects `compute_100` with LLVM 21 and `compute_75` with LLVM 7.
The kernels accept explicit pointer/count arguments. SHA-256 reads and writes
32 bytes per work item. Input and output buffers must not overlap.

Export success does not establish another PTX consumer's numerical correctness.
12 changes: 12 additions & 0 deletions examples/ptx_export/kernels/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "ptx-export-kernels"
version = "0.1.0"
edition = "2024"
publish = false

[dependencies]
cuda_std = { path = "../../../crates/cuda_std" }
sha2 = { version = "0.10", default-features = false }

[lib]
crate-type = ["cdylib", "rlib"]
29 changes: 29 additions & 0 deletions examples/ptx_export/kernels/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use cuda_std::prelude::*;
use sha2::{Digest, Sha256};

/// Add `count` floats. All pointers address buffers of at least `count` elements.
///
/// # Safety
/// Inputs must be readable and output writable, with no overlapping buffers.
#[kernel]
pub unsafe fn rust_vecadd(a: *const f32, b: *const f32, out: *mut f32, count: u32) {
let i = thread::index_1d();
if i < count {
unsafe { *out.add(i as usize) = *a.add(i as usize) + *b.add(i as usize) };
}
}

/// Hash `count` independent 32-byte messages into 32-byte digests.
///
/// # Safety
/// Input/output each address `count * 32` bytes and must not overlap.
#[kernel]
pub unsafe fn rust_sha256_32(input: *const u8, out: *mut u8, count: u32) {
let i = thread::index_1d();
if i < count {
let offset = i as usize * 32;
let message = unsafe { core::slice::from_raw_parts(input.add(offset), 32) };
let digest = Sha256::digest(message);
unsafe { core::ptr::copy_nonoverlapping(digest.as_ptr(), out.add(offset), 32) };
}
}
21 changes: 21 additions & 0 deletions examples/ptx_export/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use cuda_builder::CudaBuilder;
use std::{env, fs, path::PathBuf};

fn main() -> Result<(), Box<dyn std::error::Error>> {
let output = PathBuf::from(
env::args_os()
.nth(1)
.unwrap_or_else(|| "artifacts/ptx".into()),
);
fs::create_dir_all(&output)?;
let output = output.canonicalize()?;
let kernels = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("kernels");
let ptx = CudaBuilder::new(kernels)
.copy_to(output.join("rust_kernels.ptx"))
.final_module_path(output.join("final-module.ll"))
.emit_llvm_ir(true)
.build()
.map_err(|error| std::io::Error::other(format!("PTX compilation failed: {error:?}")))?;
println!("Exported {}", ptx.display());
Ok(())
}