cuda.core.utils.make_program_cache_key#

cuda.core.utils.make_program_cache_key(
*,
code: str | bytes,
code_type: str,
options: ProgramOptions,
target_type: str,
name_expressions: Sequence[str | bytes | bytearray] = (),
extra_digest: bytes | None = None,
) bytes#

Build a stable cache key from compile inputs.

Parameters:
  • code – Source text. str is encoded as UTF-8.

  • code_type – One of "c++", "ptx", "nvvm".

  • options – A cuda.core.ProgramOptions. Its arch must be set (the default ProgramOptions.__post_init__ populates it from the current device).

  • target_type – One of "ptx", "cubin", "ltoir".

  • name_expressions – Optional iterable of mangled-name lookups. Order is not significant. Elements may be str or bytes; "foo" and b"foo" produce distinct keys because Program.compile records the original Python object as the ObjectCode.symbol_mapping key, and get_kernel lookups must use the same type the cache key recorded. bytearray is rejected because Program.compile stores each element as a dict key and bytearray is unhashable.

  • extra_digest – Caller-supplied bytes mixed into the key. Required whenever cuda.core.ProgramOptions sets any option that pulls in external file content (include_path, pre_include, pch, use_pch, pch_dir) – the cache cannot read those files on the caller’s behalf, so the caller must fingerprint the header / PCH surface and pass it here. Callers may pass this for other inputs too (embedded kernels, generated sources, etc.).

Returns:

A 32-byte blake2b digest suitable for use as a cache key.

Return type:

bytes

Raises:
  • ValueError – If options sets an option with compile-time side effects (such as create_pch) – a cache hit skips compilation, so the side effect would not occur.

  • ValueError – If extra_digest is None while options sets any option whose compilation effect depends on external file content that the key cannot otherwise observe.

Examples

For most workflows you should not call make_program_cache_key yourself – pass cache= to cuda.core.Program.compile(), which derives the key, returns the cached ObjectCode on hit, and stores the compile result on miss:

from cuda.core import Program, ProgramOptions
from cuda.core.utils import FileStreamProgramCache

source = 'extern "C" __global__ void k(int *a){ *a = 1; }'
options = ProgramOptions(arch="sm_80")

with FileStreamProgramCache() as cache:
    obj = Program(source, "c++", options=options).compile("cubin", cache=cache)

Call make_program_cache_key directly when the compile inputs require an extra_digest (the cache cannot read external file content on the caller’s behalf) – Program.compile(cache=...) refuses those inputs with a ValueError pointing here:

from cuda.core import ObjectCode
from cuda.core.utils import FileStreamProgramCache, make_program_cache_key

with FileStreamProgramCache() as cache:
    key = make_program_cache_key(
        code=source,
        code_type="c++",
        options=options,
        target_type="cubin",
        extra_digest=fingerprint_headers(options.include_path),
    )
    data = cache.get(key)
    if data is None:
        obj = Program(source, "c++", options=options).compile("cubin")
        cache[key] = obj  # extracts bytes(obj.code)
    else:
        obj = ObjectCode.from_cubin(data)

The cache stores raw binary bytes – cubin / PTX / LTO-IR with no pickle, JSON, or framing – so entry files are directly consumable by external NVIDIA tools (cuobjdump, nvdisasm, …). Note that an ObjectCode round-tripped through the cache loses symbol_mapping: callers that compile with name_expressions and rely on get_kernel(name_expression) after a cache hit must either compile fresh or look up the mangled symbol explicitly.

Options that read external files (include_path, pre_include, pch, use_pch, pch_dir; use_libdevice=True on the NVVM path; and on NVRTC, an options.name with a directory component, which NVRTC uses for relative-include resolution) require extra_digest – fingerprint the bytes the compiler will pull in and pass that digest so changes to those files force a cache miss. Options that have compile-time side effects (create_pch, time, fdevice_time_trace) cannot be cached and raise ValueError; compile directly, or disable the flag, for those cases.