@@ -41,6 +41,77 @@ def to_set(edge_index):
4141 return set ([(i , j ) for i , j in edge_index .t ().tolist ()])
4242
4343
44+ def _assert_knn_within_cuda (
45+ out_cuda ,
46+ out_triton ,
47+ x ,
48+ y ,
49+ k ,
50+ cosine ,
51+ tol = None ,
52+ ):
53+ if tol is None :
54+ tol = 2 * torch .finfo (x .dtype ).eps
55+ m = y .size (0 )
56+ cuda_rows = out_cuda [0 ]
57+ cuda_cols = out_cuda [1 ]
58+ triton_rows = out_triton [0 ]
59+ triton_cols = out_triton [1 ]
60+ y_f = y .float ()
61+ x_f = x .float ()
62+ y_norm = torch .linalg .norm (y_f , dim = 1 )
63+ if cosine :
64+ x_cuda = x_f [cuda_cols ]
65+ y_cuda = y_f [cuda_rows ]
66+ cuda_dot = (x_cuda * y_cuda ).sum (dim = 1 )
67+ cuda_norm = torch .linalg .norm (x_cuda , dim = 1 )
68+ cuda_dist = 1.0 - cuda_dot / (cuda_norm * y_norm [cuda_rows ])
69+ x_triton = x_f [triton_cols ]
70+ y_triton = y_f [triton_rows ]
71+ triton_dot = (x_triton * y_triton ).sum (dim = 1 )
72+ triton_norm = torch .linalg .norm (x_triton , dim = 1 )
73+ triton_dist = 1.0 - triton_dot / (
74+ triton_norm * y_norm [triton_rows ]
75+ )
76+ else :
77+ x_cuda = x_f [cuda_cols ]
78+ y_cuda = y_f [cuda_rows ]
79+ cuda_dist = ((x_cuda - y_cuda ) ** 2 ).sum (dim = 1 )
80+ x_triton = x_f [triton_cols ]
81+ y_triton = y_f [triton_rows ]
82+ triton_dist = ((x_triton - y_triton ) ** 2 ).sum (dim = 1 )
83+ cuda_max = torch .full (
84+ (m ,),
85+ - float ("inf" ),
86+ device = y .device ,
87+ dtype = torch .float32 ,
88+ )
89+ cuda_max .scatter_reduce_ (
90+ 0 ,
91+ cuda_rows ,
92+ cuda_dist ,
93+ reduce = "amax" ,
94+ include_self = True ,
95+ )
96+ triton_thresh = cuda_max [triton_rows ] + tol
97+ margin = (triton_dist - triton_thresh ).max ().item ()
98+ if cosine :
99+ x_ref = x_f [triton_cols ]
100+ y_ref = y_f [triton_rows ]
101+ ref_dot = (x_ref * y_ref ).sum (dim = 1 )
102+ ref_norm = torch .linalg .norm (x_ref , dim = 1 )
103+ ref_dist = 1.0 - ref_dot / (ref_norm * y_norm [triton_rows ])
104+ else :
105+ x_ref = x_f [triton_cols ]
106+ y_ref = y_f [triton_rows ]
107+ ref_dist = ((x_ref - y_ref ) ** 2 ).sum (dim = 1 )
108+ max_diff = torch .abs (triton_dist - ref_dist ).max ().item ()
109+ print (f"[knn][match] max_margin={ margin :.6e} tol={ tol :.1e} " )
110+ print (f"[knn][match] max_diff={ max_diff :.6e} tol={ tol :.1e} " )
111+ assert (triton_dist <= triton_thresh ).all ()
112+ assert max_diff <= tol
113+
114+
44115def _make_batch (
45116 num_nodes : int ,
46117 num_groups : int ,
@@ -195,11 +266,14 @@ def triton_fn():
195266 if i == 0 :
196267 out_cuda = cuda_fn ()
197268 out_triton = triton_fn ()
198- for a , b in zip (
199- sorted (list (to_set (out_cuda ))),
200- sorted (list (to_set (out_triton ))),
201- ):
202- assert a == b
269+ _assert_knn_within_cuda (
270+ out_cuda ,
271+ out_triton ,
272+ x ,
273+ y ,
274+ k = 16 ,
275+ cosine = True ,
276+ )
203277 else :
204278 triton_fn ()
205279 torch .cuda .synchronize ()
@@ -255,11 +329,14 @@ def triton_fn():
255329 if i == 0 :
256330 out_cuda = cuda_fn ()
257331 out_triton = triton_fn ()
258- for a , b in zip (
259- sorted (list (to_set (out_cuda ))),
260- sorted (list (to_set (out_triton ))),
261- ):
262- assert a == b
332+ _assert_knn_within_cuda (
333+ out_cuda ,
334+ out_triton ,
335+ x ,
336+ y ,
337+ k = 16 ,
338+ cosine = False ,
339+ )
263340 else :
264341 triton_fn ()
265342 torch .cuda .synchronize ()
0 commit comments