77import ctypes .wintypes
88import os
99import struct
10+ import sys
1011from collections .abc import Iterator
1112from typing import TYPE_CHECKING
1213
6263]
6364psapi .EnumProcessModules .restype = ctypes .wintypes .BOOL
6465
66+ _CUPTI_DIAGNOSTICS_ENVVAR = "CUDA_PATHFINDER_WINDOWS_CUPTI_ALREADY_LOADED_DIAGNOSTICS"
67+
68+
69+ def _cupti_diagnostics_enabled (desc_name : str ) -> bool :
70+ raw = os .environ .get (_CUPTI_DIAGNOSTICS_ENVVAR )
71+ if desc_name != "cupti" or raw is None :
72+ return False
73+ return raw .strip ().lower () not in ("" , "0" , "false" , "no" )
74+
75+
76+ def _emit_cupti_diagnostic (message : str ) -> None :
77+ sys .stderr .write (f"[cuda.pathfinder][cupti-diag] { message } \n " )
78+
6579
6680def ctypes_handle_to_unsigned_int (handle : ctypes .wintypes .HMODULE ) -> int :
6781 """Convert ctypes HMODULE to unsigned int."""
@@ -142,20 +156,52 @@ def _iter_loaded_module_handles() -> Iterator[ctypes.wintypes.HMODULE]:
142156 capacity = count
143157
144158
145- def _find_loaded_module (dll_names : tuple [str , ...]) -> tuple [ctypes .wintypes .HMODULE , str ] | None :
159+ def _find_loaded_module (
160+ dll_names : tuple [str , ...],
161+ * ,
162+ diagnostics_enabled : bool = False ,
163+ ) -> tuple [ctypes .wintypes .HMODULE , str ] | None :
146164 wanted = {dll_name .casefold () for dll_name in dll_names }
165+ relevant_modules : list [str ] = []
147166 for handle in _iter_loaded_module_handles ():
148167 abs_path = abs_path_for_dynamic_library ("loaded module" , handle )
149- if os .path .basename (abs_path ).casefold () in wanted :
168+ basename = os .path .basename (abs_path )
169+ basename_casefold = basename .casefold ()
170+ if diagnostics_enabled and ("cupti" in basename_casefold or "nvperf" in basename_casefold ):
171+ relevant_modules .append (f"0x{ ctypes_handle_to_unsigned_int (handle ):x} :{ abs_path } " )
172+ if basename_casefold in wanted :
173+ if diagnostics_enabled :
174+ _emit_cupti_diagnostic (
175+ "enumerated relevant modules: " + (" | " .join (relevant_modules ) if relevant_modules else "<none>" )
176+ )
177+ _emit_cupti_diagnostic (
178+ f"enumeration match: basename={ basename !r} abs_path={ abs_path !r} "
179+ f" handle=0x{ ctypes_handle_to_unsigned_int (handle ):x} "
180+ )
150181 return handle , abs_path
182+ if diagnostics_enabled :
183+ _emit_cupti_diagnostic (
184+ "enumerated relevant modules: " + (" | " .join (relevant_modules ) if relevant_modules else "<none>" )
185+ )
151186 return None
152187
153188
154189def check_if_already_loaded_from_elsewhere (desc : LibDescriptor , have_abs_path : bool ) -> LoadedDL | None :
190+ diagnostics_enabled = _cupti_diagnostics_enabled (desc .name )
191+ basename_probe_results : list [str ] = []
155192 for dll_name in desc .windows_dlls :
156193 handle = kernel32 .GetModuleHandleW (dll_name )
194+ if diagnostics_enabled :
195+ handle_text = "0x0" if not handle else f"0x{ ctypes_handle_to_unsigned_int (handle ):x} "
196+ basename_probe_results .append (f"{ dll_name } ={ handle_text } " )
157197 if handle :
158198 abs_path = abs_path_for_dynamic_library (desc .name , handle )
199+ if diagnostics_enabled :
200+ _emit_cupti_diagnostic ("basename GetModuleHandleW results: " + ", " .join (basename_probe_results ))
201+ _emit_cupti_diagnostic (
202+ f"basename match: dll_name={ dll_name !r} abs_path={ abs_path !r} "
203+ f" handle=0x{ ctypes_handle_to_unsigned_int (handle ):x} "
204+ )
159205 if have_abs_path and desc .requires_add_dll_directory :
160206 # This is a side-effect if the pathfinder loads the library via
161207 # load_with_abs_path(). To make the side-effect more deterministic,
@@ -164,7 +210,9 @@ def check_if_already_loaded_from_elsewhere(desc: LibDescriptor, have_abs_path: b
164210 return LoadedDL (abs_path , True , ctypes_handle_to_unsigned_int (handle ), "was-already-loaded-from-elsewhere" )
165211 # Observed on newer Windows CUPTI builds: GetModuleHandleW(basename)
166212 # can miss an already loaded DLL, so fall back to enumerating loaded modules.
167- loaded = _find_loaded_module (desc .windows_dlls )
213+ if diagnostics_enabled :
214+ _emit_cupti_diagnostic ("basename GetModuleHandleW results: " + ", " .join (basename_probe_results ))
215+ loaded = _find_loaded_module (desc .windows_dlls , diagnostics_enabled = diagnostics_enabled )
168216 if loaded is not None :
169217 handle , abs_path = loaded
170218 if have_abs_path and desc .requires_add_dll_directory :
0 commit comments