Skip to content

fix(core): accept the documented str symbol_mapping in ObjectCode.get_kernel - #2585

Open
LeSingh1 wants to merge 1 commit into
NVIDIA:mainfrom
LeSingh1:module-get-kernel-str-symbol-mapping
Open

fix(core): accept the documented str symbol_mapping in ObjectCode.get_kernel#2585
LeSingh1 wants to merge 1 commit into
NVIDIA:mainfrom
LeSingh1:module-get-kernel-str-symbol-mapping

Conversation

@LeSingh1

@LeSingh1 LeSingh1 commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Problem

Every ObjectCode.from_* constructor annotates and documents symbol_mapping: dict[str, str] | None"a dictionary specifying how the unmangled symbol names (as keys) should be mapped to the mangled names". get_kernel encodes the name only on the mapping miss path (_module.pyx:802-808):

        try:
            name = self._sym_map[name]
        except KeyError:
            if isinstance(name, str):
                name = name.encode()

        cdef KernelHandle h_kernel = create_kernel_handle(self._h_library, <const char*>name)

On a hit, name is rebound to the mapped value and handed straight to <const char*>. cuda_core sets no c_string_type / c_string_encoding directive — build_hooks.py:224 passes only embedsignature, warn.deprecated.IF and freethreading_compatible — so Cython's default applies and a str raises TypeError: expected bytes, str found.

The documented form therefore fails for exactly the names it exists to translate:

obj = ObjectCode.from_cubin(cubin, symbol_mapping={"saxpy<double>": mangled_str})
obj.get_kernel("saxpy<double>")   # TypeError: expected bytes, str found
obj.get_kernel("not_in_the_map")  # works

Why this has gone unnoticed: Program.compile fills the mapping from nvrtcGetLoweredName (_program.pyx:905-906), whose const char* Cython converts to bytes. Every existing test round-trips mod.symbol_mapping straight back into a from_* constructor (test_module.py:340, 354, 367, 380, 395, 412, 422, 435), so only bytes values are ever exercised. ObjectCode.symbol_mapping is likewise annotated dict[str, str] while returning bytes values.

Fix

Move the encode past the lookup so both value types work. Compile-produced mappings are byte-for-byte unaffected.

Tests

test_object_code_symbol_mapping_accepts_str_values, modelled on the adjacent test_object_code_load_cubin: decode the compile-produced mapping to dict[str, str], rebuild the ObjectCode from it, and get_kernel through a mapped name.

What I ran

Environment: macOS, no CUDA driver and no CUDA toolkit, so cuda.core cannot be built or imported here.

  • Did not run: the new test or the rest of test_module.py — they need a built cuda.core and a GPU.
  • Ran (teeth check): Cython is installed here, so I compiled the before/after name-handling verbatim into a standalone extension (language_level=3, no string directives — matching build_hooks.py) and drove it with both value types:
  hit, str value  (documented dict[str, str])      before -> TypeError: expected bytes, str found   after -> b'_Z5saxpyIdEvT_PKS0_S2_PS0_i'
  hit, bytes value (what Program.compile stores)   before -> b'_Z5saxpyIdEvT_PKS0_S2_PS0_i'         after -> b'_Z5saxpyIdEvT_PKS0_S2_PS0_i'
  miss, str name                                   before -> b'saxpy'                               after -> b'saxpy'
  miss, bytes name                                 before -> b'saxpy'                               after -> b'saxpy'

So the change fixes the documented case and leaves the other three byte-identical.

  • Ran: python -m py_compile, ruff check, ruff format --check on cuda_core/tests/test_module.py — clean, no new findings against a main baseline.
  • Checked: grep -rn "c_string_type\|c_string_encoding" cuda_core/ finds nothing, so Cython's default strchar* conversion (which rejects str) is what applies.
  • Not changed here: ObjectCode.symbol_mapping's -> dict[str, str] annotation still describes bytes values for compile-produced mappings. Correcting that annotation is a separate, wider question (it would need to become dict[str, str | bytes], or the compile path would need to decode), so I left it rather than widen this PR.

…_kernel

Every `ObjectCode.from_*` constructor annotates and documents
`symbol_mapping: dict[str, str] | None`. `get_kernel` encodes the name only
on the mapping MISS path:

    try:
        name = self._sym_map[name]
    except KeyError:
        if isinstance(name, str):
            name = name.encode()

    cdef KernelHandle h_kernel = create_kernel_handle(self._h_library, <const char*>name)

On a HIT, `name` is rebound to the mapped value and handed straight to
`<const char*>`. cuda_core sets no `c_string_type`/`c_string_encoding`
directive (build_hooks.py passes only embedsignature, warn.deprecated.IF and
freethreading_compatible), so Cython's default applies and a `str` raises
"TypeError: expected bytes, str found".

So the documented form fails for exactly the names it is supposed to
translate:

    ObjectCode.from_cubin(cubin, symbol_mapping={"saxpy<double>": mangled_str})
        .get_kernel("saxpy<double>")     # TypeError
        .get_kernel("not_in_the_map")    # fine

The reason this has gone unnoticed: `Program.compile` fills the mapping from
`nvrtcGetLoweredName`, whose `const char*` Cython converts to `bytes`, and
every existing test round-trips `mod.symbol_mapping` straight back into a
`from_*` constructor -- so only bytes values are ever exercised.

Move the encode past the lookup so both value types work. Compile-produced
mappings are unaffected.
@copy-pr-bot

copy-pr-bot Bot commented Aug 9, 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.

@github-actions github-actions Bot added the cuda.core Everything related to the cuda.core module label Aug 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cuda.core Everything related to the cuda.core module

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant