NVIDIA / NVIDIA/cuda-python

[FEA] cuda.core: adopt nvFatbin for multi-arch fat binary assembly

Open
#2,356 0 comments 0 reactions 1 assignee View on GitHub

@isVoid is already working on this.

Since Jul 23, 2026.

cuda.core feature
Dominant language
Cython
Stars
3.4k
Forks
329
Avg merge
1d 23h
Merged PRs (30d)
116

Description

Summary

cuda.bindings.nvfatbin (available since cuda-bindings 12.9.x) is not used anywhere in cuda.core
product code today — it only appears as a test helper that builds a two-arch fatbin to exercise
ObjectCode.from_fatbin:
https://github.com/NVIDIA/cuda-python/blob/c000331de6c37aa4565af74b001271ffcf6d5c99/cuda_core/tests/test_module.py#L144-L175

cuda.core covers the consume side of fat binaries
(ObjectCode.from_fatbin)
but has no produce side: to target several architectures, users must juggle N per-arch
ObjectCodes or shell out to the fatbinary CLI. nvFatbin closes this gap in-process.

Use cases:

  • compile per arch (CUBIN/PTX/LTO-IR) and ship one artifact; PTX/LTO-IR entries keep JIT
    forward-compatibility on newer GPUs
  • AOT kernel caches / packaging: one fatbin per kernel suite instead of per-arch files
  • bundling Tile IR (nvFatbinAddTileIR) once #1322 / #1434 land

Underlying C APIs to cover

The entire libnvfatbin surface (pythonic names from
cuda.bindings.nvfatbin @ v13.3.1):

C API cuda.bindings.nvfatbin Purpose
nvFatbinCreate create(options, options_count) new fatbin handle; options include -compress=<bool>, -compress-all, -compress-mode=<mode>, -host=<name>, -32/-64
nvFatbinAddCubin add_cubin(handle, code, size, arch, identifier) add SASS for one arch
nvFatbinAddPTX add_ptx(handle, code, size, arch, identifier, options_cmd_line) add PTX (JIT-compatible entry)
nvFatbinAddLTOIR add_ltoir(handle, code, size, arch, identifier, options_cmd_line) add LTO-IR
nvFatbinAddReloc add_reloc(handle, code, size) add relocatable PTX from a host object
nvFatbinAddTileIR add_tile_ir(handle, code, size, identifier, options_cmd_line) add Tile IR (documented since CUDA 13.1; pairs with #1434)
nvFatbinAddIndex add_index(handle, code, size, identifier) new in cuda-bindings 13.3.x (not yet in the public nvFatbin docs)
nvFatbinSize / nvFatbinGet size(handle) / get(handle, buffer) serialize the finished fatbin
nvFatbinDestroy destroy(handle) release the handle
nvFatbinVersion / nvFatbinGetErrorString version() / get_error_string(result) introspection / error text

The bindings load libnvfatbin lazily, so each entry point also requires a new-enough runtime
library — option/entry-point support must be version-gated with actionable error messages,
in the spirit of #337.

Design sketch (draft — needs design-meeting review)

[!IMPORTANT]
The sketch below is a starting point only, not a settled design. API shape, names, and
scope should all be reviewed in the cuda.core design meeting before implementation.

Option A — one-shot constructor, no intermediate handle exposed:

code: ObjectCode = ObjectCode.from_parts(     # all names TBD
    [objcode_sm100a,                          # ObjectCode in, kind/arch from metadata...
     (ptx, "ptx", "sm_120")],                 # ...or raw bytes + explicit kind/arch
    options=...,
)                                             # ObjectCode with code_type="fatbin"

Option B — a small builder object (fb = FatbinBundler(...); fb.add(...); fb.finalize()),
only if Option A's argument shape gets unwieldy — cuda.core uses the builder pattern sparingly
(CUDA graph construction is the only case today).

Option C — Program-level sugar that compiles for multiple archs and bundles the results
(e.g. Program.compile("fatbin", archs=[...])) — likely a follow-up on top of A/B rather than
initial scope, since it multiplies compilation work behind one call.

Open questions for the meeting:

  1. Can kind/arch be inferred when the input is an ObjectCode (PTX carries its arch in
    text; cubin would need parsing or an explicit argument)?
  2. Options surface: a FatbinOptions dataclass mirroring ProgramOptions/LinkerOptions
    style, vs. plain kwargs?
  3. Handle lifetime: route through the _cpp resource-handle registry like other native handles?
  4. Version gating & diagnostics for older libnvfatbin (no add_tile_ir/add_index), per #337.
  5. Is Option C in scope at all initially?

References

-- Leo's bot

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.