22import csv
33import math
44import os
5+ import sys
6+ from pathlib import Path
7+
8+
9+ PROJECT_ROOT = Path (__file__ ).resolve ().parents [1 ]
10+ SRC_ROOT = PROJECT_ROOT / "src"
11+ if SRC_ROOT .is_dir ():
12+ sys .path .insert (0 , str (SRC_ROOT ))
513
614import torch
715
1826DEFAULT_INDEX_DTYPES = "int32,int64"
1927WARMUP = 20
2028ITERS = 200
29+ KERNEL_GRAPH_BATCH = 100
2130
2231
2332def _fmt_ms (value ):
@@ -82,8 +91,8 @@ def _parse_cases(raw):
8291 left , right = item .split (":" , 1 )
8392 dense_size = int (left )
8493 nnz = int (right )
85- if dense_size < 0 or nnz < 0 :
86- raise ValueError (f"case values must be non-negative : { item } " )
94+ if dense_size <= 0 or nnz <= 0 :
95+ raise ValueError (f"case values must be positive : { item } " )
8796 pairs .append ((dense_size , nnz ))
8897 if not pairs :
8998 raise ValueError ("case list is empty" )
@@ -172,7 +181,7 @@ def _print_header():
172181 print ("-" * 196 )
173182 print (
174183 f"{ 'ValueReq' :>14} { 'ValueEff' :>18} { 'Index' :>6} { 'Dense' :>10} { 'NNZ' :>10} "
175- f"{ 'IFB' :>4} { 'PT (ms)' :>10} { 'FS (ms)' :>10} { 'CS(ms)' :>10} "
184+ f"{ 'IFB' :>4} { 'FS (ms)' :>10} { 'PT (ms)' :>10} { 'CS(ms)' :>10} "
176185 f"{ 'FS/PT' :>8} { 'FS/CS' :>8} { 'Status' :>6} { 'Err(FS)' :>12} { 'Err(CS)' :>12} "
177186 )
178187 print ("-" * 196 )
@@ -182,7 +191,7 @@ def _print_row(row):
182191 print (
183192 f"{ row ['value_dtype_req' ]:>14} { row ['value_dtype_compute' ]:>18} { row ['index_dtype' ]:>6} "
184193 f"{ row ['dense_size' ]:>10,d} { row ['nnz' ]:>10,d} { str (row ['index_fallback_applied' ]):>4} "
185- f"{ _fmt_ms (row ['pytorch_ms ' ]):>10} { _fmt_ms (row ['triton_ms ' ]):>10} { _fmt_ms (row ['cusparse_ms' ]):>10} "
194+ f"{ _fmt_ms (row ['triton_ms ' ]):>10} { _fmt_ms (row ['pytorch_ms ' ]):>10} { _fmt_ms (row ['cusparse_ms' ]):>10} "
186195 f"{ _fmt_speedup (row ['triton_speedup_vs_pytorch' ]):>8} { _fmt_speedup (row ['triton_speedup_vs_cusparse' ]):>8} "
187196 f"{ row ['status' ]:>6} { _fmt_err (row ['triton_max_error' ]):>12} { _fmt_err (row ['cusparse_max_error' ]):>12} "
188197 )
@@ -201,9 +210,11 @@ def run_cli(args):
201210 print ("=" * 180 )
202211 print ("FLAGSPARSE GATHER BENCHMARK/VALIDATION" )
203212 print ("=" * 180 )
213+ print (f"FlagSparse source: { Path (ast .__file__ ).resolve ()} " )
204214 print (f"GPU: { torch .cuda .get_device_name (0 )} " )
205215 print (
206216 f"Warmup: { args .warmup } | Iterations: { args .iters } | "
217+ f"Kernel graph batch: { KERNEL_GRAPH_BATCH } | "
207218 f"index_fallback_policy: { args .index_fallback_policy } "
208219 )
209220 print ()
@@ -242,6 +253,18 @@ def run_cli(args):
242253 verify = result ["verification" ]
243254 params = result ["parameters" ]
244255 backend = result ["backend_status" ]
256+ timing_method = perf .get ("kernel_timing_method" )
257+ graph_batch = params .get ("kernel_graph_batch" )
258+ if timing_method != "cuda_graph_event_amortized_device_estimate" :
259+ raise RuntimeError (
260+ "loaded benchmark_gather_case does not provide CUDA Graph timing; "
261+ f"flagsparse was loaded from { Path (ast .__file__ ).resolve ()} "
262+ )
263+ if graph_batch != KERNEL_GRAPH_BATCH :
264+ raise RuntimeError (
265+ "unexpected gather graph batch: "
266+ f"expected { KERNEL_GRAPH_BATCH } , got { graph_batch } "
267+ )
245268 status = _status_from_result (verify )
246269 if status != "PASS" :
247270 failed_cases += 1
@@ -263,6 +286,8 @@ def run_cli(args):
263286 "cusparse_ms" : perf .get ("cusparse_ms" ),
264287 "triton_speedup_vs_pytorch" : perf .get ("triton_speedup_vs_pytorch" ),
265288 "triton_speedup_vs_cusparse" : perf .get ("triton_speedup_vs_cusparse" ),
289+ "kernel_timing_method" : timing_method ,
290+ "kernel_graph_batch" : graph_batch ,
266291 "triton_match_pytorch" : verify .get ("triton_match_pytorch" ),
267292 "cusparse_match_pytorch" : verify .get ("cusparse_match_pytorch" ),
268293 "triton_max_error" : verify .get ("triton_max_error" ),
@@ -285,6 +310,8 @@ def run_cli(args):
285310 )
286311 except Exception as exc :
287312 failed_cases += 1
313+ error_text = f"{ exc .__class__ .__name__ } : { exc } "
314+ print (f"\n ERROR [{ case_id } ]: { error_text } " )
288315 row = {
289316 "case_id" : case_id ,
290317 "gpu" : torch .cuda .get_device_name (0 ),
@@ -301,12 +328,14 @@ def run_cli(args):
301328 "cusparse_ms" : None ,
302329 "triton_speedup_vs_pytorch" : None ,
303330 "triton_speedup_vs_cusparse" : None ,
331+ "kernel_timing_method" : "cuda_graph_event_amortized_device_estimate" ,
332+ "kernel_graph_batch" : KERNEL_GRAPH_BATCH ,
304333 "triton_match_pytorch" : None ,
305334 "cusparse_match_pytorch" : None ,
306335 "triton_max_error" : None ,
307336 "cusparse_max_error" : None ,
308- "cusparse_unavailable_reason" : str ( exc ) ,
309- "index_fallback_reason" : str ( exc ) ,
337+ "cusparse_unavailable_reason" : error_text ,
338+ "index_fallback_reason" : error_text ,
310339 "status" : "ERROR" ,
311340 }
312341 summary_rows .append (row )
@@ -334,6 +363,8 @@ def run_cli(args):
334363 "cusparse_ms" ,
335364 "triton_speedup_vs_pytorch" ,
336365 "triton_speedup_vs_cusparse" ,
366+ "kernel_timing_method" ,
367+ "kernel_graph_batch" ,
337368 "triton_match_pytorch" ,
338369 "cusparse_match_pytorch" ,
339370 "triton_max_error" ,
0 commit comments