1111import logging
1212import threading
1313import datetime
14- import time
1514from concurrent .futures import ThreadPoolExecutor , as_completed
1615from typing import List , Dict , Any , Callable , Optional
1716
1817logger = logging .getLogger (__name__ )
1918
19+
2020class ParallelEvaluationManager :
2121 """
2222 Manages parallel evaluation of queries using multiple workers.
@@ -32,7 +32,7 @@ def __init__(self, workers: int = 16):
3232 self .workers = workers
3333 self .stats_lock = threading .Lock ()
3434 self .save_lock = threading .Lock ()
35-
35+
3636 # Statistics
3737 self .reset_stats ()
3838
@@ -55,7 +55,10 @@ def get_stats(self) -> Dict[str, Any]:
5555 "skipped" : self .skipped_count ,
5656 "failed" : self .failed_count ,
5757 "already_evaluated" : self .already_evaluated_count ,
58- "total_duration_min" : (datetime .datetime .now () - self .start_time ).total_seconds () / 60
58+ "total_duration_min" : (
59+ datetime .datetime .now () - self .start_time
60+ ).total_seconds ()
61+ / 60 ,
5962 }
6063
6164 def evaluate_entries_parallel (
@@ -65,7 +68,7 @@ def evaluate_entries_parallel(
6568 save_func : Optional [Callable ] = None ,
6669 save_interval : int = 50 ,
6770 total_count : int = 0 ,
68- ** extra_kwargs
71+ ** extra_kwargs ,
6972 ) -> Dict [str , Any ]:
7073 """
7174 Process entries in parallel using ThreadPoolExecutor.
@@ -89,12 +92,12 @@ def evaluate_entries_parallel(
8992 total_count = len (tasks )
9093
9194 logger .info (f"Starting parallel evaluation with { self .workers } workers" )
92-
95+
9396 def worker_task (idx : int , data : Any ) -> bool :
9497 try :
9598 # Execute evaluation
9699 success = evaluation_func (idx , data , ** extra_kwargs )
97-
100+
98101 # Update statistics
99102 with self .stats_lock :
100103 if success :
@@ -103,20 +106,24 @@ def worker_task(idx: int, data: Any) -> bool:
103106 self .skipped_count += 1
104107 self .processed_count += 1
105108 current_processed = self .processed_count
106-
109+
107110 # Handle periodic saving
108- if save_func and save_interval > 0 and current_processed % save_interval == 0 :
111+ if (
112+ save_func
113+ and save_interval > 0
114+ and current_processed % save_interval == 0
115+ ):
109116 with self .save_lock :
110117 save_func ()
111-
118+
112119 stats = self .get_stats ()
113120 logger .info (
114121 f"Progress: { current_processed } /{ total_count } | "
115122 f"Evaluated: { stats ['evaluated' ]} | "
116123 f"Skipped: { stats ['skipped' ]} | "
117124 f"Elapsed: { stats ['total_duration_min' ]:.1f} min | Saved checkpoint"
118125 )
119-
126+
120127 return success
121128 except Exception as e :
122129 logger .error (f"Error in worker task (index { idx } ): { e } " , exc_info = True )
@@ -131,7 +138,7 @@ def worker_task(idx: int, data: Any) -> bool:
131138 executor .submit (worker_task , idx , data ): (idx , data )
132139 for idx , data in tasks
133140 }
134-
141+
135142 for future in as_completed (future_to_task ):
136143 try :
137144 future .result ()
0 commit comments