Skip to content

Commit 1a94027

Browse files
committed
fixup! feat(core.utils): require extra_digest for NVVM use_libdevice=True
1 parent 3c97d22 commit 1a94027

File tree

2 files changed

+58
-7
lines changed

2 files changed

+58
-7
lines changed

cuda_core/cuda/core/utils/_program_cache.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,22 @@ def make_program_cache_key(
510510
f"Disable the option, or compile directly without the cache."
511511
)
512512

513+
# NVVM with ``use_libdevice=True`` reads external libdevice bitcode at
514+
# compile time (see Program_init in _program.pyx). The file is resolved
515+
# from the active toolkit, so a changed CUDA_HOME / libdevice upgrade
516+
# changes the linked output without touching any key input the cache can
517+
# observe. Require the caller to supply an ``extra_digest`` that
518+
# fingerprints the libdevice bytes (or simply disable use_libdevice for
519+
# caching-sensitive workflows).
520+
if backend == "nvvm" and extra_digest is None and getattr(options, "use_libdevice", None):
521+
raise ValueError(
522+
"make_program_cache_key() refuses to build an NVVM key with "
523+
"use_libdevice=True and no extra_digest: the linked libdevice "
524+
"bitcode can change out from under a cached ObjectCode. Pass an "
525+
"extra_digest that fingerprints the libdevice file you intend "
526+
"to link against, or disable use_libdevice."
527+
)
528+
513529
# External-content options are NVRTC-only. ``Program.compile`` for PTX
514530
# inputs runs ``_translate_program_options``, which drops
515531
# ``include_path``/``pre_include``/``pch``/``use_pch``/``pch_dir``

cuda_core/tests/test_program_cache.py

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -445,19 +445,54 @@ def test_make_program_cache_key_use_libdevice_ignored_for_non_nvvm(code_type, co
445445
assert k_off == k_on == k_none
446446

447447

448+
def test_make_program_cache_key_nvvm_use_libdevice_requires_extra_digest():
449+
"""NVVM with ``use_libdevice=True`` links an external libdevice bitcode
450+
file whose contents the cache can't observe; require an extra_digest
451+
or the cached ObjectCode can silently drift under a toolkit upgrade."""
452+
from cuda.core.utils import make_program_cache_key
453+
454+
with pytest.raises(ValueError, match="libdevice"):
455+
make_program_cache_key(
456+
code="abc",
457+
code_type="nvvm",
458+
options=_opts(use_libdevice=True),
459+
target_type="ptx",
460+
)
461+
# With an extra_digest, it's accepted; different digests produce
462+
# different keys so a caller can represent a libdevice change.
463+
k_a = make_program_cache_key(
464+
code="abc",
465+
code_type="nvvm",
466+
options=_opts(use_libdevice=True),
467+
target_type="ptx",
468+
extra_digest=b"libdev-a" * 4,
469+
)
470+
k_b = make_program_cache_key(
471+
code="abc",
472+
code_type="nvvm",
473+
options=_opts(use_libdevice=True),
474+
target_type="ptx",
475+
extra_digest=b"libdev-b" * 4,
476+
)
477+
assert k_a != k_b
478+
479+
448480
def test_make_program_cache_key_nvvm_use_libdevice_false_equals_none():
449481
"""Program_init gates ``use_libdevice`` on truthiness, so False and None
450-
compile identically and must hash the same way."""
451-
# With the NVVM probe mocked so the NVVM portion is stable.
452-
from cuda.core.utils import _program_cache
453-
454-
# Use real probe; the key differences come only from use_libdevice here.
482+
compile identically and must hash the same way. (True without an
483+
extra_digest is rejected; see test_...requires_extra_digest.)"""
455484
k_none = _make_key(code="abc", code_type="nvvm", target_type="ptx", options=_opts(use_libdevice=None))
456485
k_false = _make_key(code="abc", code_type="nvvm", target_type="ptx", options=_opts(use_libdevice=False))
457-
k_true = _make_key(code="abc", code_type="nvvm", target_type="ptx", options=_opts(use_libdevice=True))
458486
assert k_none == k_false
487+
# With an explicit extra_digest, True produces a different key.
488+
k_true = _make_key(
489+
code="abc",
490+
code_type="nvvm",
491+
target_type="ptx",
492+
options=_opts(use_libdevice=True),
493+
extra_digest=b"libdev" * 8,
494+
)
459495
assert k_true != k_none
460-
_ = _program_cache # silence unused warning
461496

462497

463498
def test_make_program_cache_key_nvvm_probe_changes_key(monkeypatch):

0 commit comments

Comments
 (0)