Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
10/06/17 14:13:21 (5 years ago)
Author:
pfleck
Message:

#2822 Merged branch to trunk

Location:
trunk/sources/HeuristicLab.Optimization
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/sources/HeuristicLab.Optimization

  • trunk/sources/HeuristicLab.Optimization/3.3/MetaOptimizers/Experiment.cs

    r15339 r15408  
    9797    }
    9898
     99    [Storable]
     100    private int numberOfWorkers = 1;
     101    public int NumberOfWorkers {
     102      get { return numberOfWorkers; }
     103      set {
     104        if (value < 1) throw new ArgumentException("Number of Workers must not be lower than one.");
     105        numberOfWorkers = value;
     106      }
     107    }
     108
    99109    public IEnumerable<IOptimizer> NestedOptimizers {
    100110      get {
     
    111121    private bool experimentStarted = false;
    112122    private bool experimentStopped = false;
     123
    113124    private readonly ManualResetEventSlim allOptimizerFinished = new ManualResetEventSlim(false); // this indicates that all started optimizers have been paused or stopped
    114125
     
    155166      experimentStarted = original.experimentStarted;
    156167      experimentStopped = original.experimentStopped;
     168      numberOfWorkers = original.numberOfWorkers;
    157169      Initialize();
    158170    }
     
    192204      if ((ExecutionState != ExecutionState.Prepared) && (ExecutionState != ExecutionState.Paused))
    193205        throw new InvalidOperationException(string.Format("Start not allowed in execution state \"{0}\".", ExecutionState));
    194       if (!Optimizers.Any(x => x.ExecutionState == ExecutionState.Prepared || x.ExecutionState == ExecutionState.Paused)) return;
     206
     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;
    195210
    196211      experimentStarted = true;
    197212      experimentStopped = false;
    198       allOptimizerFinished.Reset();
    199       IOptimizer optimizer;
    200       while ((optimizer = Optimizers.FirstOrDefault(x => x.ExecutionState == ExecutionState.Prepared || x.ExecutionState == ExecutionState.Paused)) != null) {
    201         // a race-condition may occur when the optimizer has changed the state by itself in the meantime
    202         try { optimizer.Start(cancellationToken); } catch (InvalidOperationException) { }
    203         if (ExecutionState == ExecutionState.Paused || ExecutionState == ExecutionState.Stopped) break;
    204       }
    205       allOptimizerFinished.Wait();
     213
     214      var startedOptimizers = new Dictionary<IOptimizer, Task>(); // track already started optimizers (.StartAsync does not set the executionstate immediately)
     215      using (var availableWorkers = new SemaphoreSlim(NumberOfWorkers, NumberOfWorkers)) {
     216        while (runnableOptimizers.Any(o => !startedOptimizers.ContainsKey(o))) {
     217          try {
     218            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            }
     228          } catch (InvalidOperationException) { } catch (OperationCanceledException) { }
     229        }
     230
     231        Task.WaitAll(startedOptimizers.Values.ToArray()); // retreive exeptions of the asyncrounously started optimizer
     232        allOptimizerFinished.Wait();
     233      }
    206234    }
    207235    public async Task StartAsync() { await StartAsync(CancellationToken.None); }
     
    218246      foreach (IOptimizer optimizer in Optimizers.Where(x => x.ExecutionState == ExecutionState.Started)) {
    219247        // a race-condition may occur when the optimizer has changed the state by itself in the meantime
    220         try { optimizer.Pause(); } catch (InvalidOperationException) { }
     248        try { optimizer.Pause(); } catch (InvalidOperationException) { } catch (NotSupportedException) { }
    221249      }
    222250    }
     
    372400    }
    373401    private void optimizer_Paused(object sender, EventArgs e) {
    374       lock (locker)
    375         if (Optimizers.All(x => x.ExecutionState != ExecutionState.Started)) OnPaused();
     402      lock (locker) {
     403        if (Optimizers.All(x => x.ExecutionState != ExecutionState.Started)) {
     404          OnPaused();
     405        }
     406        experimentStarted = false;
     407      }
    376408    }
    377409    private void optimizer_Prepared(object sender, EventArgs e) {
     
    389421        } else {
    390422          if (experimentStarted && Optimizers.Any(x => (x.ExecutionState == ExecutionState.Prepared) || (x.ExecutionState == ExecutionState.Paused))) return;
    391           else if (Optimizers.All(x => x.ExecutionState == ExecutionState.Stopped)) OnStopped();
    392           else if (Optimizers.Any(x => (x.ExecutionState == ExecutionState.Prepared) || (x.ExecutionState == ExecutionState.Paused)) && Optimizers.All(o => o.ExecutionState != ExecutionState.Started)) OnPaused();
     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          }
    393428        }
    394429      }
Note: See TracChangeset for help on using the changeset viewer.