@@ -37,11 +37,12 @@ def _get_new_nvlddmkm(start_local_str: str) -> list[str]:
3737 return ["<event query failed: %s>" % e ]
3838
3939
40- def _run_round (mode : str , blocks : int , threads : int , stress_iters : int ) -> dict :
40+ def _run_round (mode : str , blocks : int , threads : int , stress_iters : int , mb : int = 32 ) -> dict :
4141 exe = _checker_path ()
4242 if not os .path .exists (exe ):
4343 return {"error" : f"L2 checker not found: { exe } " }
44- cmd = [exe , "--blocks" , str (blocks ), "--threads" , str (threads ), "--rounds" , "1" , "--mode" , mode ]
44+ cmd = [exe , "--blocks" , str (blocks ), "--threads" , str (threads ), "--rounds" , "1" ,
45+ "--mode" , mode , "--mb" , str (mb )]
4546 if mode == "load" :
4647 cmd += ["--stress-iters" , str (stress_iters )]
4748 try :
@@ -55,6 +56,31 @@ def _run_round(mode: str, blocks: int, threads: int, stress_iters: int) -> dict:
5556 return {"errors" : int (m .group (1 )), "elapsed_ms" : float (m .group (2 ))}
5657
5758
59+ def _diagnose_cuda () -> None :
60+ """Print CUDA/driver/memory diagnostics that help explain checker failures."""
61+ try :
62+ r = subprocess .run (
63+ ["nvidia-smi" , "--query-gpu=name,driver_version,memory.total,memory.used" ,
64+ "--format=csv,noheader,nounits" ],
65+ capture_output = True , text = True , encoding = "utf-8" , errors = "replace" , timeout = 15 ,
66+ )
67+ if r .returncode == 0 and r .stdout .strip ():
68+ print ("nvidia-smi:" , r .stdout .strip ())
69+ else :
70+ print ("nvidia-smi: unavailable" , file = sys .stderr )
71+ except Exception as e :
72+ print (f"nvidia-smi: unavailable ({ e } )" , file = sys .stderr )
73+
74+
75+ def _auto_select_mb (stress_iters : int ) -> int | None :
76+ """Find the largest checker buffer that can be allocated on this system."""
77+ for mb in (32 , 16 , 8 , 4 , 2 ):
78+ row = _run_round ("idle" , 1 , 1 , stress_iters , mb = mb )
79+ if "error" not in row :
80+ return mb
81+ return None
82+
83+
5884def _gpu_blocks () -> int :
5985 """Pick a heuristic block count for the detected RTX 50-series GPU.
6086
@@ -98,19 +124,30 @@ def _gpu_blocks() -> int:
98124
99125def run_l2_test (blocks : int | None = None , threads : int = 256 ,
100126 stress_iters : int = 100000 ,
101- idle_rounds : int = 3 , load_rounds : int = 3 ) -> bool :
127+ idle_rounds : int = 3 , load_rounds : int = 3 ,
128+ mb : int | None = None ) -> bool :
102129 """Run the L2 integrity test. Returns True only if all rounds pass."""
103130 if blocks is None :
104131 blocks = _gpu_blocks ()
105132 print ("=== XBAR L2 stability test ===" )
106133 print ("Using checker:" , _checker_path ())
107134 print (f"Using blocks={ blocks } threads={ threads } (auto-selected if not specified)" )
135+ if mb is None :
136+ mb = _auto_select_mb (stress_iters )
137+ if mb is None :
138+ print ("ERROR: could not allocate even a 2 MiB CUDA buffer." , file = sys .stderr )
139+ _diagnose_cuda ()
140+ print ("RESULT: FAIL" )
141+ return False
142+ print (f"Auto-selected checker buffer: { mb } MiB" )
143+ else :
144+ print (f"Using checker buffer: { mb } MiB" )
108145 start_local = time .strftime ("%Y-%m-%dT%H:%M:%S" )
109146 all_ok = True
110147 errors_total = 0
111148 for mode , rounds in (("idle" , idle_rounds ), ("load" , load_rounds )):
112149 for i in range (rounds ):
113- row = _run_round (mode , blocks , threads , stress_iters )
150+ row = _run_round (mode , blocks , threads , stress_iters , mb = mb )
114151 if "error" in row :
115152 print (f" round { i + 1 } { mode } : ERROR { row ['error' ]} " )
116153 all_ok = False
@@ -126,5 +163,7 @@ def run_l2_test(blocks: int | None = None, threads: int = 256,
126163 if new_events :
127164 all_ok = False
128165 print ("Total L2 errors:" , errors_total )
166+ if not all_ok :
167+ _diagnose_cuda ()
129168 print ("RESULT:" , "PASS" if all_ok else "FAIL" )
130169 return all_ok
0 commit comments