From 0c71c3565a7936472a17f87c0176a3d4279dda38 Mon Sep 17 00:00:00 2001 From: Leo Fang Date: Mon, 21 Apr 2025 22:03:21 +0000 Subject: [PATCH 1/7] also search for conda nvvm on windows --- cuda_bindings/cuda/bindings/_internal/nvvm_windows.pyx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/cuda_bindings/cuda/bindings/_internal/nvvm_windows.pyx b/cuda_bindings/cuda/bindings/_internal/nvvm_windows.pyx index 76ce23254..9243bf072 100644 --- a/cuda_bindings/cuda/bindings/_internal/nvvm_windows.pyx +++ b/cuda_bindings/cuda/bindings/_internal/nvvm_windows.pyx @@ -41,7 +41,7 @@ cdef void* __nvvmGetProgramLog = NULL cdef inline list get_site_packages(): - return [site.getusersitepackages()] + site.getsitepackages() + return [site.getusersitepackages()] + site.getsitepackages() + ["conda"] cdef load_library(const int driver_ver): @@ -60,9 +60,13 @@ cdef load_library(const int driver_ver): else: break - # Next, check if DLLs are installed via pip + # Next, check if DLLs are installed via pip or conda for sp in get_site_packages(): - mod_path = os.path.join(sp, "nvidia", "cuda_nvcc", "nvvm", "bin") + if sp == "conda" and "CONDA_PREFIX" in os.environ: + # nvvm is not under $CONDA_PREFIX/lib, so it's not in the default search path + mod_path = os.path.join(os.environ["CONDA_PREFIX"], "Library", "nvvm", "bin") + else: + mod_path = os.path.join(sp, "nvidia", "cuda_nvcc", "nvvm", "bin") if not os.path.isdir(mod_path): continue os.add_dll_directory(mod_path) From a14d95eb9bedb6472e85be37d8d9cbd04192bb11 Mon Sep 17 00:00:00 2001 From: Leo Fang Date: Mon, 21 Apr 2025 22:03:37 +0000 Subject: [PATCH 2/7] fix comment for conda nvvm on linux --- cuda_bindings/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cuda_bindings/setup.py b/cuda_bindings/setup.py index d9fa93d5c..ed84ef4f1 100644 --- a/cuda_bindings/setup.py +++ b/cuda_bindings/setup.py @@ -390,7 +390,7 @@ def build_extension(self, ext): # to /site-packages/nvidia/cuda_nvcc/nvvm/lib64/ rel1 = "$ORIGIN/../../../nvidia/cuda_nvcc/nvvm/lib64" # from /lib/python3.*/site-packages/cuda/bindings/_internal/ - # to /lib/nvvm/lib64/ + # to /nvvm/lib64/ rel2 = "$ORIGIN/../../../../../../nvvm/lib64" ldflag = f"-Wl,--disable-new-dtags,-rpath,{rel1},-rpath,{rel2}" else: From 21a7fb4a8dfbf71145b3389cf1d7cab0a252ec67 Mon Sep 17 00:00:00 2001 From: Leo Fang Date: Mon, 21 Apr 2025 21:56:04 -0700 Subject: [PATCH 3/7] fix path loop & dll name --- cuda_bindings/cuda/bindings/_bindings/cynvrtc.pyx.in | 4 +++- cuda_bindings/cuda/bindings/_internal/nvjitlink_windows.pyx | 4 +++- cuda_bindings/cuda/bindings/_internal/nvvm_windows.pyx | 6 ++++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/cuda_bindings/cuda/bindings/_bindings/cynvrtc.pyx.in b/cuda_bindings/cuda/bindings/_bindings/cynvrtc.pyx.in index a0f8a27a0..707858904 100644 --- a/cuda_bindings/cuda/bindings/_bindings/cynvrtc.pyx.in +++ b/cuda_bindings/cuda/bindings/_bindings/cynvrtc.pyx.in @@ -75,7 +75,9 @@ cdef int cuPythonInit() except -1 nogil: mod_path = os.path.join(sp, "nvidia", "cuda_nvrtc", "bin") if not os.path.isdir(mod_path): continue - os.add_dll_directory(mod_path) + else: + os.add_dll_directory(mod_path) + break LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x00001000 LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x00000100 try: diff --git a/cuda_bindings/cuda/bindings/_internal/nvjitlink_windows.pyx b/cuda_bindings/cuda/bindings/_internal/nvjitlink_windows.pyx index c8c7e6b29..c392c78fc 100644 --- a/cuda_bindings/cuda/bindings/_internal/nvjitlink_windows.pyx +++ b/cuda_bindings/cuda/bindings/_internal/nvjitlink_windows.pyx @@ -67,7 +67,9 @@ cdef load_library(const int driver_ver): mod_path = os.path.join(sp, "nvidia", "nvJitLink", "bin") if not os.path.isdir(mod_path): continue - os.add_dll_directory(mod_path) + else: + os.add_dll_directory(mod_path) + break try: handle = win32api.LoadLibraryEx( # Note: LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR needs an abs path... diff --git a/cuda_bindings/cuda/bindings/_internal/nvvm_windows.pyx b/cuda_bindings/cuda/bindings/_internal/nvvm_windows.pyx index 9243bf072..9ca927aac 100644 --- a/cuda_bindings/cuda/bindings/_internal/nvvm_windows.pyx +++ b/cuda_bindings/cuda/bindings/_internal/nvvm_windows.pyx @@ -50,7 +50,7 @@ cdef load_library(const int driver_ver): for suffix in get_nvvm_dso_version_suffix(driver_ver): if len(suffix) == 0: continue - dll_name = "nvvm64_40_0" + dll_name = "nvvm64_40_0.dll" # First check if the DLL has been loaded by 3rd parties try: @@ -69,7 +69,9 @@ cdef load_library(const int driver_ver): mod_path = os.path.join(sp, "nvidia", "cuda_nvcc", "nvvm", "bin") if not os.path.isdir(mod_path): continue - os.add_dll_directory(mod_path) + else: + os.add_dll_directory(mod_path) + break try: handle = win32api.LoadLibraryEx( # Note: LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR needs an abs path... From a0baf7197b2e4e1e7898751a8a1ced14aa3cbe06 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 22 Apr 2025 08:21:41 -0700 Subject: [PATCH 4/7] Ensure mod_path is always defined when used. Make DLL search order consistent between all three cases. --- .../cuda/bindings/_bindings/cynvrtc.pyx.in | 53 +++++++++---------- .../bindings/_internal/nvjitlink_windows.pyx | 38 +++++++------ .../cuda/bindings/_internal/nvvm_windows.pyx | 45 ++++++++-------- 3 files changed, 67 insertions(+), 69 deletions(-) diff --git a/cuda_bindings/cuda/bindings/_bindings/cynvrtc.pyx.in b/cuda_bindings/cuda/bindings/_bindings/cynvrtc.pyx.in index 707858904..4f2dbd655 100644 --- a/cuda_bindings/cuda/bindings/_bindings/cynvrtc.pyx.in +++ b/cuda_bindings/cuda/bindings/_bindings/cynvrtc.pyx.in @@ -60,38 +60,37 @@ cdef int cuPythonInit() except -1 nogil: except: handle = None - # Else try default search - if not handle: - LOAD_LIBRARY_SAFE_CURRENT_DIRS = 0x00002000 - try: - handle = win32api.LoadLibraryEx("nvrtc64_120_0.dll", 0, LOAD_LIBRARY_SAFE_CURRENT_DIRS) - except: - pass - - # Final check if DLLs can be found within pip installations + # Check if DLLs can be found within pip installations if not handle: site_packages = [site.getusersitepackages()] + site.getsitepackages() for sp in site_packages: mod_path = os.path.join(sp, "nvidia", "cuda_nvrtc", "bin") - if not os.path.isdir(mod_path): - continue - else: + if os.path.isdir(mod_path): os.add_dll_directory(mod_path) - break - LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x00001000 - LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x00000100 - try: - handle = win32api.LoadLibraryEx( - # Note: LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR needs an abs path... - os.path.join(mod_path, "nvrtc64_120_0.dll"), - 0, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR) - - # Note: nvrtc64_120_0.dll calls into nvrtc-builtins64_*.dll which is - # located in the same mod_path. - # Update PATH environ so that the two dlls can find each other - os.environ["PATH"] = os.pathsep.join((os.environ.get("PATH", ""), mod_path)) - except: - pass + LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x00001000 + LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x00000100 + try: + handle = win32api.LoadLibraryEx( + # Note: LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR needs an abs path... + os.path.join(mod_path, "nvrtc64_120_0.dll"), + 0, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR) + + # Note: nvrtc64_120_0.dll calls into nvrtc-builtins64_*.dll which is + # located in the same mod_path. + # Update PATH environ so that the two dlls can find each other + os.environ["PATH"] = os.pathsep.join((os.environ.get("PATH", ""), mod_path)) + except: + pass + else: + break + else: + # Else try default search + # Only reached if DLL wasn't found in any site-package path + LOAD_LIBRARY_SAFE_CURRENT_DIRS = 0x00002000 + try: + handle = win32api.LoadLibraryEx("nvrtc64_120_0.dll", 0, LOAD_LIBRARY_SAFE_CURRENT_DIRS) + except: + pass if not handle: raise RuntimeError('Failed to LoadLibraryEx nvrtc64_120_0.dll') diff --git a/cuda_bindings/cuda/bindings/_internal/nvjitlink_windows.pyx b/cuda_bindings/cuda/bindings/_internal/nvjitlink_windows.pyx index c392c78fc..ee06dc757 100644 --- a/cuda_bindings/cuda/bindings/_internal/nvjitlink_windows.pyx +++ b/cuda_bindings/cuda/bindings/_internal/nvjitlink_windows.pyx @@ -65,28 +65,26 @@ cdef load_library(const int driver_ver): # Next, check if DLLs are installed via pip for sp in get_site_packages(): mod_path = os.path.join(sp, "nvidia", "nvJitLink", "bin") - if not os.path.isdir(mod_path): - continue - else: + if os.path.isdir(mod_path): os.add_dll_directory(mod_path) - break - try: - handle = win32api.LoadLibraryEx( - # Note: LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR needs an abs path... - os.path.join(mod_path, dll_name), - 0, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR) - except: - pass - else: - break - - # Finally, try default search - try: - handle = win32api.LoadLibrary(dll_name) - except: - pass + try: + handle = win32api.LoadLibraryEx( + # Note: LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR needs an abs path... + os.path.join(mod_path, dll_name), + 0, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR) + except: + pass + else: + break else: - break + # Finally, try default search + # Only reached if DLL wasn't found in any site-package path + try: + handle = win32api.LoadLibrary(dll_name) + except: + pass + else: + break else: raise RuntimeError('Failed to load nvJitLink') diff --git a/cuda_bindings/cuda/bindings/_internal/nvvm_windows.pyx b/cuda_bindings/cuda/bindings/_internal/nvvm_windows.pyx index 9ca927aac..4eb30e3ca 100644 --- a/cuda_bindings/cuda/bindings/_internal/nvvm_windows.pyx +++ b/cuda_bindings/cuda/bindings/_internal/nvvm_windows.pyx @@ -62,33 +62,34 @@ cdef load_library(const int driver_ver): # Next, check if DLLs are installed via pip or conda for sp in get_site_packages(): - if sp == "conda" and "CONDA_PREFIX" in os.environ: + if sp == "conda": # nvvm is not under $CONDA_PREFIX/lib, so it's not in the default search path - mod_path = os.path.join(os.environ["CONDA_PREFIX"], "Library", "nvvm", "bin") + conda_prefix = os.environ.get("CONDA_PREFIX") + if conda_prefix is None: + continue + mod_path = os.path.join(conda_prefix, "Library", "nvvm", "bin") else: mod_path = os.path.join(sp, "nvidia", "cuda_nvcc", "nvvm", "bin") - if not os.path.isdir(mod_path): - continue - else: + if os.path.isdir(mod_path): os.add_dll_directory(mod_path) - break - try: - handle = win32api.LoadLibraryEx( - # Note: LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR needs an abs path... - os.path.join(mod_path, dll_name), - 0, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR) - except: - pass - else: - break - - # Finally, try default search - try: - handle = win32api.LoadLibrary(dll_name) - except: - pass + try: + handle = win32api.LoadLibraryEx( + # Note: LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR needs an abs path... + os.path.join(mod_path, dll_name), + 0, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR) + except: + pass + else: + break else: - break + # Finally, try default search + # Only reached if DLL wasn't found in any site-package path + try: + handle = win32api.LoadLibrary(dll_name) + except: + pass + else: + break else: raise RuntimeError('Failed to load nvvm') From 03e6e4a170906fb144e967701deb22b1c28840fb Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 22 Apr 2025 08:58:21 -0700 Subject: [PATCH 5/7] Fix bug in previous commit: need to break out of loop over suffix if site-package DLL was found. Using the most obvious approach to solve this problem: return immediately on success. --- .../bindings/_internal/nvjitlink_windows.pyx | 30 +++++++------------ .../cuda/bindings/_internal/nvvm_windows.pyx | 29 +++++++----------- 2 files changed, 20 insertions(+), 39 deletions(-) diff --git a/cuda_bindings/cuda/bindings/_internal/nvjitlink_windows.pyx b/cuda_bindings/cuda/bindings/_internal/nvjitlink_windows.pyx index ee06dc757..979820442 100644 --- a/cuda_bindings/cuda/bindings/_internal/nvjitlink_windows.pyx +++ b/cuda_bindings/cuda/bindings/_internal/nvjitlink_windows.pyx @@ -56,11 +56,9 @@ cdef load_library(const int driver_ver): # First check if the DLL has been loaded by 3rd parties try: - handle = win32api.GetModuleHandle(dll_name) + return win32api.GetModuleHandle(dll_name) except: pass - else: - break # Next, check if DLLs are installed via pip for sp in get_site_packages(): @@ -68,28 +66,20 @@ cdef load_library(const int driver_ver): if os.path.isdir(mod_path): os.add_dll_directory(mod_path) try: - handle = win32api.LoadLibraryEx( + return win32api.LoadLibraryEx( # Note: LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR needs an abs path... os.path.join(mod_path, dll_name), 0, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR) except: pass - else: - break - else: - # Finally, try default search - # Only reached if DLL wasn't found in any site-package path - try: - handle = win32api.LoadLibrary(dll_name) - except: - pass - else: - break - else: - raise RuntimeError('Failed to load nvJitLink') - - assert handle != 0 - return handle + # Finally, try default search + # Only reached if DLL wasn't found in any site-package path + try: + return win32api.LoadLibrary(dll_name) + except: + pass + + raise RuntimeError('Failed to load nvJitLink') cdef int _check_or_init_nvjitlink() except -1 nogil: diff --git a/cuda_bindings/cuda/bindings/_internal/nvvm_windows.pyx b/cuda_bindings/cuda/bindings/_internal/nvvm_windows.pyx index 4eb30e3ca..638ecaaf6 100644 --- a/cuda_bindings/cuda/bindings/_internal/nvvm_windows.pyx +++ b/cuda_bindings/cuda/bindings/_internal/nvvm_windows.pyx @@ -54,11 +54,9 @@ cdef load_library(const int driver_ver): # First check if the DLL has been loaded by 3rd parties try: - handle = win32api.GetModuleHandle(dll_name) + return win32api.GetModuleHandle(dll_name) except: pass - else: - break # Next, check if DLLs are installed via pip or conda for sp in get_site_packages(): @@ -73,28 +71,21 @@ cdef load_library(const int driver_ver): if os.path.isdir(mod_path): os.add_dll_directory(mod_path) try: - handle = win32api.LoadLibraryEx( + return win32api.LoadLibraryEx( # Note: LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR needs an abs path... os.path.join(mod_path, dll_name), 0, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR) except: pass - else: - break - else: - # Finally, try default search - # Only reached if DLL wasn't found in any site-package path - try: - handle = win32api.LoadLibrary(dll_name) - except: - pass - else: - break - else: - raise RuntimeError('Failed to load nvvm') - assert handle != 0 - return handle + # Finally, try default search + # Only reached if DLL wasn't found in any site-package path + try: + handle = win32api.LoadLibrary(dll_name) + except: + pass + + raise RuntimeError('Failed to load nvvm') cdef int _check_or_init_nvvm() except -1 nogil: From 98d7a91d31f6abc50485ae5c4d2fc26e8858c5e1 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 22 Apr 2025 09:24:59 -0700 Subject: [PATCH 6/7] Move LOAD_LIBRARY_SEARCH_* constants outside loop. --- cuda_bindings/cuda/bindings/_bindings/cynvrtc.pyx.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cuda_bindings/cuda/bindings/_bindings/cynvrtc.pyx.in b/cuda_bindings/cuda/bindings/_bindings/cynvrtc.pyx.in index 4f2dbd655..caf36d40e 100644 --- a/cuda_bindings/cuda/bindings/_bindings/cynvrtc.pyx.in +++ b/cuda_bindings/cuda/bindings/_bindings/cynvrtc.pyx.in @@ -62,13 +62,13 @@ cdef int cuPythonInit() except -1 nogil: # Check if DLLs can be found within pip installations if not handle: + LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x00001000 + LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x00000100 site_packages = [site.getusersitepackages()] + site.getsitepackages() for sp in site_packages: mod_path = os.path.join(sp, "nvidia", "cuda_nvrtc", "bin") if os.path.isdir(mod_path): os.add_dll_directory(mod_path) - LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x00001000 - LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x00000100 try: handle = win32api.LoadLibraryEx( # Note: LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR needs an abs path... From 1a05efc8dff734b5105f3c01e0c5f7691172c776 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 22 Apr 2025 09:26:16 -0700 Subject: [PATCH 7/7] Fix oversight (forgot to replace one assignment with return) --- cuda_bindings/cuda/bindings/_internal/nvvm_windows.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cuda_bindings/cuda/bindings/_internal/nvvm_windows.pyx b/cuda_bindings/cuda/bindings/_internal/nvvm_windows.pyx index 638ecaaf6..9f507e8e1 100644 --- a/cuda_bindings/cuda/bindings/_internal/nvvm_windows.pyx +++ b/cuda_bindings/cuda/bindings/_internal/nvvm_windows.pyx @@ -81,7 +81,7 @@ cdef load_library(const int driver_ver): # Finally, try default search # Only reached if DLL wasn't found in any site-package path try: - handle = win32api.LoadLibrary(dll_name) + return win32api.LoadLibrary(dll_name) except: pass