11import json
22import math
3+ import time
34from pathlib import Path
45from typing import Dict , List , Tuple
6+ from tqdm import tqdm
57
68import numpy as np
79
@@ -58,9 +60,20 @@ def _load_cached(path: Path) -> List[Dict[str, float]]:
5860 "standard_pass_at_k" : float (run ["standard_pass_at_k" ]),
5961 "zk_pass_at_k" : float (run ["zk_pass_at_k" ]),
6062 }
61- # 可选保存的 zk_n(每簇 padding 长度),若存在则保留
62- if "zk_n" in run :
63- cleaned ["zk_n" ] = float (run ["zk_n" ])
63+ # 可选保存的附加信息(每簇 padding 长度、各阶段时间),若存在则保留
64+ optional_keys = [
65+ "zk_n" ,
66+ "bruteforce_time" ,
67+ "standard_train_time" ,
68+ "standard_query_time" ,
69+ "zk_train_time" ,
70+ "zk_query_time" ,
71+ "standard_recall_at_k" ,
72+ "zk_recall_at_k" ,
73+ ]
74+ for key in optional_keys :
75+ if key in run :
76+ cleaned [key ] = float (run [key ])
6477 out .append (cleaned )
6578 return out
6679
@@ -139,14 +152,18 @@ def _run_once(
139152 raise ValueError ("top_k must be in [1, N]" )
140153
141154 # 1. 预先计算 brute-force L2 KNN 作为 ground truth
155+ t0 = time .time ()
142156 gt_topk = [brute_force_knn (base , queries [i ], top_k ) for i in range (Q )]
157+ bruteforce_time = time .time () - t0
158+ print (f"[acc_bench] bruteforce_time={ bruteforce_time :.3f} s" )
143159
144160 # 为本次 run 生成不同的随机种子,使多次 run 之间有随机性
145161 rng = np .random .default_rng ()
146162 std_seed = int (rng .integers (0 , 2 ** 31 - 1 ))
147163 zk_seed = int (rng .integers (0 , 2 ** 31 - 1 ))
148164
149165 # 2. 非 ZK 版本:使用浮点 standard IVF-PQ
166+ t0 = time .time ()
150167 std_labels , std_center , std_code_books , std_quant_vecs , std_id_groups = (
151168 ivf_pq_learn (
152169 base ,
@@ -156,9 +173,13 @@ def _run_once(
156173 random_state = std_seed ,
157174 )
158175 )
176+ standard_train_time = time .time () - t0
177+ print (f"[acc_bench] standard_train_time={ standard_train_time :.3f} s" )
159178
160179 std_pass_list : List [float ] = []
161- for i in range (Q ):
180+ std_recall_list : List [float ] = []
181+ t0 = time .time ()
182+ for i in tqdm (range (Q ), "非zk版本" ):
162183 pred = ivf_pq_query (
163184 queries [i ],
164185 top_k ,
@@ -171,8 +192,13 @@ def _run_once(
171192 )
172193 inter = np .intersect1d (pred , gt_topk [i ])
173194 std_pass_list .append (float (inter .size ) / float (top_k ))
195+ best_gt = int (gt_topk [i ][0 ])
196+ std_recall_list .append (1.0 if best_gt in pred else 0.0 )
197+ standard_query_time = time .time () - t0
198+ print (f"[acc_bench] standard_query_time={ standard_query_time :.3f} s" )
174199
175200 # 3. ZK 版本:首先 rescale,然后使用 zk 版本的 learn + query
201+ t0 = time .time ()
176202 scaled_base , v_min , v_max = rescale_database (base , scale_n )
177203 if cluster_bound is not None :
178204 (
@@ -207,9 +233,13 @@ def _run_once(
207233
208234 # 计算 ZK 证明中每簇需要 padding 到的容量 n(power-of-two 容量)
209235 zk_n = _build_cluster_capacity (zk_id_groups , n_probe )
236+ zk_train_time = time .time () - t0
237+ print (f"[acc_bench] zk_train_time={ zk_train_time :.3f} s" )
210238
211239 zk_pass_list : List [float ] = []
212- for i in range (Q ):
240+ zk_recall_list : List [float ] = []
241+ t0 = time .time ()
242+ for i in tqdm (range (Q ), "zk版本" ):
213243 scaled_query = rescale_query (queries [i ], scale_n , v_min , v_max )
214244 pred_zk , _ = zk_ivf_pq_query (
215245 scaled_query ,
@@ -223,11 +253,22 @@ def _run_once(
223253 )
224254 inter = np .intersect1d (pred_zk , gt_topk [i ])
225255 zk_pass_list .append (float (inter .size ) / float (top_k ))
256+ best_gt = int (gt_topk [i ][0 ])
257+ zk_recall_list .append (1.0 if best_gt in pred_zk else 0.0 )
258+ zk_query_time = time .time () - t0
259+ print (f"[acc_bench] zk_query_time={ zk_query_time :.3f} s" )
226260
227261 result = {
228262 "standard_pass_at_k" : float (np .mean (std_pass_list )),
229263 "zk_pass_at_k" : float (np .mean (zk_pass_list )),
264+ "standard_recall_at_k" : float (np .mean (std_recall_list )),
265+ "zk_recall_at_k" : float (np .mean (zk_recall_list )),
230266 "zk_n" : float (zk_n ),
267+ "bruteforce_time" : float (bruteforce_time ),
268+ "standard_train_time" : float (standard_train_time ),
269+ "standard_query_time" : float (standard_query_time ),
270+ "zk_train_time" : float (zk_train_time ),
271+ "zk_query_time" : float (zk_query_time ),
231272 }
232273 return result
233274
0 commit comments