From d4e7db4ed2dc6799dac3c2dc396baab47da9e43d Mon Sep 17 00:00:00 2001 From: Sam Foreman Date: Tue, 14 Jul 2026 08:18:40 -0500 Subject: [PATCH 1/2] fix(pyzes): resolve libze_loader via portable path fallback pyzes _LoadZeLibrary hardcoded the Debian/Ubuntu multiarch path /usr/lib/x86_64-linux-gnu/libze_loader.so.1 on Linux. On non-Debian systems (RHEL/SUSE/Fedora, and HPC images such as ALCF Aurora/Sunspot) the loader lives in /usr/lib64, so `import pyzes` -- and therefore torch.xpu.is_available() / device_count() which import it -- failed with: OSError: /usr/lib/x86_64-linux-gnu/libze_loader.so.1: cannot open shared object file: No such file or directory Give the Linux branch the same possible_paths fallback the Windows branch already uses: try the bare soname first (so the dynamic linker resolves it via LD_LIBRARY_PATH/ld.so.cache/RUNPATH -- works on every distro, including Debian), then fall back to the Debian multiarch dir, /usr/lib64, and /usr/lib. Also drop the now-redundant trailing linux CDLL(libName). Verified on ALCF Sunspot (Intel Max 1550, RHEL-family, oneAPI 2026.1.0): torch.xpu.is_available() -> True, device_count() -> 12 after the fix. Signed-off-by: Sam Foreman --- bindings/sysman/python/source/pyzes.py | 34 +++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/bindings/sysman/python/source/pyzes.py b/bindings/sysman/python/source/pyzes.py index 5ba6bfaf..c0c5766d 100644 --- a/bindings/sysman/python/source/pyzes.py +++ b/bindings/sysman/python/source/pyzes.py @@ -69,7 +69,36 @@ def _LoadZeLibrary(): # load the library libName = "ze_loader" if sys.platform.startswith("linux"): - libName = "/usr/lib/x86_64-linux-gnu/lib" + libName + ".so.1" + soName = "lib" + libName + ".so.1" + # Try the bare soname first so the dynamic linker resolves it via + # the standard search path (LD_LIBRARY_PATH, ld.so.cache, RUNPATH). + # This works on every Linux distro. The explicit paths are kept as + # fallbacks: the Debian/Ubuntu multiarch location and the + # RHEL/SUSE/Fedora lib64 location. Hardcoding only the Debian path + # broke on non-Debian systems (e.g. HPC RHEL/SLES images), where + # the loader lives in /usr/lib64. + possible_paths = [ + soName, + "/usr/lib/x86_64-linux-gnu/" + soName, + "/usr/lib64/" + soName, + "/usr/lib/" + soName, + ] + + library_loaded = False + load_errors = [] + for path in possible_paths: + try: + gpuLib = CDLL(path) + library_loaded = True + break + except OSError as error: + load_errors.append(f"{path}: {error}") + + if not library_loaded: + raise Exception( + "Failed to load Level Zero loader on Linux. " + f"Tried paths: {possible_paths}. Errors: {load_errors}" + ) else: libName = libName + ".dll" @@ -107,9 +136,6 @@ def _LoadZeLibrary(): f"Tried paths: {possible_paths}. Errors: {load_errors}" ) - if sys.platform.startswith("linux"): - gpuLib = CDLL(libName) - if gpuLib is None: raise Exception("Failed to load library: " + str(libName)) finally: From 1f2ec5cbee8d413ec70b76b602970cc1476e87a4 Mon Sep 17 00:00:00 2001 From: Sam Foreman Date: Thu, 23 Jul 2026 14:22:59 -0500 Subject: [PATCH 2/2] fix(pyzes): raise OSError (not Exception) on Linux loader failure ctypes.CDLL raises OSError on a failed dlopen, so callers of import pyzes may catch OSError specifically. Re-raise OSError (chained from the last OSError) on total load failure instead of a generic Exception, preserving the aggregated per-path diagnostics. Addresses Copilot review comment on PR #496. Signed-off-by: Sam Foreman --- bindings/sysman/python/source/pyzes.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/bindings/sysman/python/source/pyzes.py b/bindings/sysman/python/source/pyzes.py index c0c5766d..b92f3155 100644 --- a/bindings/sysman/python/source/pyzes.py +++ b/bindings/sysman/python/source/pyzes.py @@ -86,6 +86,7 @@ def _LoadZeLibrary(): library_loaded = False load_errors = [] + last_error = None for path in possible_paths: try: gpuLib = CDLL(path) @@ -93,12 +94,17 @@ def _LoadZeLibrary(): break except OSError as error: load_errors.append(f"{path}: {error}") + last_error = error if not library_loaded: - raise Exception( + # Raise OSError (the type ctypes.CDLL itself raises on a failed + # dlopen) so callers that handle OSError specifically keep + # working, while still surfacing the aggregated per-path + # diagnostics. + raise OSError( "Failed to load Level Zero loader on Linux. " f"Tried paths: {possible_paths}. Errors: {load_errors}" - ) + ) from last_error else: libName = libName + ".dll"