Changeset 15452 for trunk/sources/HeuristicLab.Optimization
- Timestamp:
- 11/06/17 16:38:36 (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/sources/HeuristicLab.Optimization/3.3/MetaOptimizers/Experiment.cs
r15408 r15452 122 122 private bool experimentStopped = false; 123 123 124 private readonly ManualResetEventSlim allOptimizerFinished = new ManualResetEventSlim(false); // this indicates that all started optimizers have been paused or stopped 124 // track already started optimizers (.StartAsync does not set the executionstate immediately) 125 // and to avoid restarting optimizers that were manually paused/stopped by the user 126 private readonly IDictionary<IOptimizer, Task> startedOptimizers = new Dictionary<IOptimizer, Task>(); 127 private IEnumerable<IOptimizer> StartableOptimizers { 128 get { 129 return Optimizers 130 .Where(x => x.ExecutionState == ExecutionState.Prepared || x.ExecutionState == ExecutionState.Paused) 131 .Where(o => !startedOptimizers.ContainsKey(o)); // all startable optimizers that were not startet yet 132 } 133 } 125 134 126 135 public Experiment() … … 205 214 throw new InvalidOperationException(string.Format("Start not allowed in execution state \"{0}\".", ExecutionState)); 206 215 207 // Multiple enumerations of runnableOptimizers is done on purpose to get the latest list of runnnable optimizers lazily 208 var runnableOptimizers = Optimizers.Where(x => x.ExecutionState == ExecutionState.Prepared || x.ExecutionState == ExecutionState.Paused); 209 if (!runnableOptimizers.Any()) return; 216 startedOptimizers.Clear(); 217 if (!StartableOptimizers.Any()) return; 210 218 211 219 experimentStarted = true; 212 220 experimentStopped = false; 213 221 214 var startedOptimizers = new Dictionary<IOptimizer, Task>(); // track already started optimizers (.StartAsync does not set the executionstate immediately)215 222 using (var availableWorkers = new SemaphoreSlim(NumberOfWorkers, NumberOfWorkers)) { 216 while ( runnableOptimizers.Any(o => !startedOptimizers.ContainsKey(o))) {223 while (StartableOptimizers.Any()) { 217 224 try { 218 225 availableWorkers.Wait(cancellationToken); 219 if (experimentStopped || !experimentStarted) break; 220 var optimizer = runnableOptimizers.FirstOrDefault(o => !startedOptimizers.ContainsKey(o)); 221 if (optimizer != null) { 222 var startedTask = optimizer.StartAsync(cancellationToken).ContinueWith(async t => { 223 availableWorkers.Release(); // is guaranteed to be not disposed yet because Task.WaitAll blocks before the end of the using 224 await t; // trigger a potential exception on the optimizerTask 225 }); 226 startedOptimizers.Add(optimizer, startedTask.Unwrap()); // unwrap task because lambda of .ContinueWith is async 227 } 226 var optimizer = StartableOptimizers.FirstOrDefault(); 227 if (experimentStopped || !experimentStarted || optimizer == null) break; 228 229 var startedTask = optimizer.StartAsync(cancellationToken).ContinueWith(async t => { 230 availableWorkers.Release(); // is guaranteed to be not disposed yet because Task.WaitAll blocks before the end of the using 231 await t; // trigger a potential exception on the optimizerTask 232 }); 233 startedOptimizers.Add(optimizer, startedTask.Unwrap()); // unwrap task because lambda of .ContinueWith is async 228 234 } catch (InvalidOperationException) { } catch (OperationCanceledException) { } 229 235 } 230 236 231 237 Task.WaitAll(startedOptimizers.Values.ToArray()); // retreive exeptions of the asyncrounously started optimizer 232 allOptimizerFinished.Wait();233 238 } 234 239 } … … 297 302 private void OnPaused() { 298 303 ExecutionState = ExecutionState.Paused; 299 allOptimizerFinished.Set();300 304 EventHandler handler = Paused; 301 305 if (handler != null) handler(this, EventArgs.Empty); … … 304 308 private void OnStopped() { 305 309 ExecutionState = ExecutionState.Stopped; 306 allOptimizerFinished.Set();307 310 EventHandler handler = Stopped; 308 311 if (handler != null) handler(this, EventArgs.Empty); … … 400 403 } 401 404 private void optimizer_Paused(object sender, EventArgs e) { 402 lock (locker) { 403 if (Optimizers.All(x => x.ExecutionState != ExecutionState.Started)) { 404 OnPaused(); 405 } 406 experimentStarted = false; 407 } 405 UpdateExecutionState(); 408 406 } 409 407 private void optimizer_Prepared(object sender, EventArgs e) { 410 lock (locker) 411 if (Optimizers.All(x => x.ExecutionState == ExecutionState.Prepared)) OnPrepared(); 408 UpdateExecutionState(); 412 409 } 413 410 private void optimizer_Started(object sender, EventArgs e) { … … 416 413 } 417 414 private void optimizer_Stopped(object sender, EventArgs e) { 415 UpdateExecutionState(); 416 } 417 private void UpdateExecutionState() { 418 // Execution states of the Experiment are determined using the following _basic_ rules: 419 // if any Optimizer is Started => Experiment is Started (2. if) 420 // if any Optimizer is Paused => Experiment is Paused (3. if) 421 // if any Optimizer is Prepared => Experiment is Prepared (5. if) 422 // else (all Optimizer are Stopped) => Experiment is Stopped (6. if) 423 // Additional there are two extra rules: 424 // if the Experiment is running and there are still optimizers that can be started => keep the Experiment Running (1. if) 425 // if experiment-stop is pending: Stop Experiment even if there are still Prepared Optimizer (4. if) 426 418 427 lock (locker) { 419 if (experimentStopped) { 420 if (Optimizers.All(x => (x.ExecutionState == ExecutionState.Stopped) || (x.ExecutionState == ExecutionState.Prepared))) OnStopped(); 421 } else { 422 if (experimentStarted && Optimizers.Any(x => (x.ExecutionState == ExecutionState.Prepared) || (x.ExecutionState == ExecutionState.Paused))) return; 423 else if (Optimizers.All(x => x.ExecutionState == ExecutionState.Stopped)) { 424 OnStopped(); 425 } else if (Optimizers.Any(x => (x.ExecutionState == ExecutionState.Prepared) || (x.ExecutionState == ExecutionState.Paused)) && Optimizers.All(o => o.ExecutionState != ExecutionState.Started)) { 426 OnPaused(); 427 } 428 } 429 } 430 } 428 // 1. experiment is running & further startable optimizers are available => continue executing 429 if (experimentStarted && StartableOptimizers.Any()) return; 430 431 // 2. any optimizer is running => continue executing 432 else if (Optimizers.Any(x => x.ExecutionState == ExecutionState.Started)) 433 return; 434 435 // 3. any optimizer is paused => experiment paused 436 else if (Optimizers.Any(x => x.ExecutionState == ExecutionState.Paused)) 437 OnPaused(); 438 439 // 4. stop pending & all optimizers either stopped or prepared => experiment stopped 440 else if (experimentStopped) 441 OnStopped(); 442 443 // 5. any optimizer prepared => experiment prepared 444 else if (Optimizers.Any(x => x.ExecutionState == ExecutionState.Prepared)) 445 OnPrepared(); 446 447 // 6. (else) all optimizers stopped 448 else 449 OnStopped(); 450 } 451 } 452 431 453 private void optimizer_Runs_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRun> e) { 432 454 lock (runsLocker) {
Note: See TracChangeset
for help on using the changeset viewer.