Run experiments for all ideas with parallel execution support Args: base_dir: Base directory for experiments (if None, uses self.base_code_dir) results_dir: Results directory ideas: List of ideas to experiment with Returns: L
(self, base_dir, results_dir, ideas)
| 1152 | } |
| 1153 | |
| 1154 | def run_experiments(self, base_dir, results_dir, ideas): |
| 1155 | """ |
| 1156 | Run experiments for all ideas with parallel execution support |
| 1157 | |
| 1158 | Args: |
| 1159 | base_dir: Base directory for experiments (if None, uses self.base_code_dir) |
| 1160 | results_dir: Results directory |
| 1161 | ideas: List of ideas to experiment with |
| 1162 | |
| 1163 | Returns: |
| 1164 | List of experiment results |
| 1165 | """ |
| 1166 | # Use self.base_code_dir if base_dir is not provided or is empty |
| 1167 | if not base_dir: |
| 1168 | base_dir = self.base_code_dir |
| 1169 | self.logger.info(f"Using base_code_dir from init: {base_dir}") |
| 1170 | |
| 1171 | results = [] |
| 1172 | total_ideas = len(ideas) |
| 1173 | |
| 1174 | self.logger.info(f"Starting experiments for {total_ideas} ideas") |
| 1175 | self.logger.info(f"Parallel execution mode: {self.max_parallel_experiments} experiments in parallel") |
| 1176 | |
| 1177 | # Check if we should use sequential execution (backward compatible) |
| 1178 | exp_config = self.config.get("experiment", {}) |
| 1179 | max_parallel = exp_config.get("max_parallel_experiments", 1) |
| 1180 | gpu_per_experiment = exp_config.get("gpu_per_experiment", 1.0) |
| 1181 | |
| 1182 | if max_parallel == 1 and gpu_per_experiment == 1.0: |
| 1183 | # Sequential execution (original behavior) |
| 1184 | self.logger.info("Using sequential execution mode (backward compatible)") |
| 1185 | |
| 1186 | for idx, idea in enumerate(ideas, 1): |
| 1187 | result = self._run_single_experiment(idx, idea, base_dir, results_dir, total_ideas) |
| 1188 | results.append(result) |
| 1189 | |
| 1190 | else: |
| 1191 | # Parallel execution |
| 1192 | self.logger.info(f"Using parallel execution mode (max {self.max_parallel_experiments} concurrent)") |
| 1193 | |
| 1194 | with ThreadPoolExecutor(max_workers=self.max_parallel_experiments) as executor: |
| 1195 | # Submit all experiments |
| 1196 | future_to_idea = { |
| 1197 | executor.submit(self._run_single_experiment, idx, idea, base_dir, results_dir, total_ideas): (idx, idea) |
| 1198 | for idx, idea in enumerate(ideas, 1) |
| 1199 | } |
| 1200 | |
| 1201 | # Collect results as they complete |
| 1202 | for future in as_completed(future_to_idea): |
| 1203 | idx, idea = future_to_idea[future] |
| 1204 | try: |
| 1205 | result = future.result() |
| 1206 | results.append(result) |
| 1207 | except Exception as e: |
| 1208 | idea_info = self._extract_idea_info(idea) |
| 1209 | self.logger.error(f"Unexpected error for idea {idx}: {str(e)}") |
| 1210 | results.append({ |
| 1211 | 'idea_name': idea_info['name'], |
no test coverage detected