From 193d25dc8cdb7401f5402fa94694e166a6aea892 Mon Sep 17 00:00:00 2001 From: Yanqin Zhai Date: Mon, 17 Aug 2026 15:02:41 -0700 Subject: [PATCH] device: ask for the oversized-SMEM ceiling by ordinal when the binding cannot name it The gate conflated two independent version axes. Whether the mode EXISTS is the driver's answer; whether cuda-python's CUdevice_attribute carries the enum member is only about how to ASK. Refusing on the second gives up the carveout on a live combination -- driver 13.5 with a cuda-python 13.3.1 binding reports 0 although the device really offers 327 KiB, which on SM 10.7 block-scale costs 3 AB stages (8 -> 5) for nothing. Keep the driver gate and drop the binding one: name the enum member when the binding has it, else pass its ordinal, which that binding forwards fine. Only the bindings old enough to reject a bare int (they read attrib.value) genuinely cannot make the query, and those answer 0 through the narrow AttributeError arm. A real driver failure still raises rather than being masked. This supersedes #615, which fixed the same class of bug in frost/device.py before #612 moved the query here. Validated on SM 10.7 (driver 13050, cuda-python 13.3.1): the query goes 0 -> 334848, i.e. back to the real ceiling the part reports. Co-Authored-By: Claude Opus 5 (1M context) --- python/cudnn/_device.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/python/cudnn/_device.py b/python/cudnn/_device.py index 76c12e989..57b706059 100644 --- a/python/cudnn/_device.py +++ b/python/cudnn/_device.py @@ -140,16 +140,19 @@ def oversized_shared_memory_per_block(self) -> int: drv = _driver() # CU_DEVICE_ATTRIBUTE_MAX_OVERSIZED_SHARED_MEMORY_PER_BLOCK (ordinal 150) - # arrived in CUDA 13.4. It needs BOTH a new-enough driver AND a cuda-python - # whose CUdevice_attribute carries the enum member: a new driver with an old - # binding passes the version gate but the enum member is absent (accessing it - # raises, since the binding reads attrib.value). Either missing -> no such - # mode -> 0 by design (not an error). With both present the attribute is real: - # query it and let a genuine failure raise rather than masking it. - attr = getattr(drv.CUdevice_attribute, "CU_DEVICE_ATTRIBUTE_MAX_OVERSIZED_SHARED_MEMORY_PER_BLOCK", None) - if attr is None or _env.driver_version() < 13040: + # arrived in CUDA 13.4. The DRIVER decides whether the mode exists at all, + # so an older one is 0 by design (not an error). The BINDING only decides + # how to ask: a cuda-python older than the driver cannot name the enum + # member but still forwards the bare ordinal, and only bindings old enough + # to reject an int (they read attrib.value) genuinely cannot make the query + # -> 0. A real driver failure still raises rather than being masked. + if _env.driver_version() < 13040: + return 0 + attr = getattr(drv.CUdevice_attribute, "CU_DEVICE_ATTRIBUTE_MAX_OVERSIZED_SHARED_MEMORY_PER_BLOCK", 150) + try: + return int(_ck(*drv.cuDeviceGetAttribute(attr, _device_handle(self.ordinal)))) + except AttributeError: return 0 - return int(_ck(*drv.cuDeviceGetAttribute(attr, _device_handle(self.ordinal)))) @functools.cached_property def l2_cache_bytes(self) -> int: