Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
07/28/17 16:47:42 (7 years ago)
Author:
jkarder
Message:

#2258: merged r15287 into stable

Location:
stable
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • stable

  • stable/HeuristicLab.Algorithms.DataAnalysis

  • stable/HeuristicLab.Algorithms.DataAnalysis/3.4/CrossValidation.cs

    r15150 r15292  
    2525using System.Linq;
    2626using System.Threading;
     27using System.Threading.Tasks;
    2728using HeuristicLab.Collections;
    2829using HeuristicLab.Common;
     
    4243    [Storable]
    4344    private int seed;
     45
     46    private SemaphoreSlim availableWorkers; // limits the number of concurrent algorithm executions
     47    private ManualResetEventSlim allAlgorithmsFinished; // this indicates that all started algorithms have been paused or stopped
    4448
    4549    public CrossValidation()
     
    269273
    270274    public void Prepare() {
     275      if (startPending) return;
    271276      if (ExecutionState == ExecutionState.Started)
    272277        throw new InvalidOperationException(string.Format("Prepare not allowed in execution state \"{0}\".", ExecutionState));
     
    283288    }
    284289
     290    private bool startPending;
    285291    public void Start() {
    286       if ((ExecutionState != ExecutionState.Prepared) && (ExecutionState != ExecutionState.Paused))
    287         throw new InvalidOperationException(string.Format("Start not allowed in execution state \"{0}\".", ExecutionState));
    288 
    289       seed = new FastRandom().NextInt();
    290 
    291       if (Algorithm != null) {
     292      Start(CancellationToken.None);
     293    }
     294    public void Start(CancellationToken cancellationToken) {
     295      lock (locker) {
     296        if (startPending) return;
     297        startPending = true;
     298      }
     299
     300      try {
     301        if ((ExecutionState != ExecutionState.Prepared) && (ExecutionState != ExecutionState.Paused))
     302          throw new InvalidOperationException(string.Format("Start not allowed in execution state \"{0}\".", ExecutionState));
     303        seed = new FastRandom().NextInt();
     304
     305        if (Algorithm == null) return;
    292306        //create cloned algorithms
    293307        if (clonedAlgorithms.Count == 0) {
     
    330344        }
    331345
    332         //start prepared or paused cloned algorithms
    333         int startedAlgorithms = 0;
    334         foreach (IAlgorithm clonedAlgorithm in clonedAlgorithms) {
    335           if (startedAlgorithms < NumberOfWorkers.Value) {
    336             if (clonedAlgorithm.ExecutionState == ExecutionState.Prepared ||
    337                 clonedAlgorithm.ExecutionState == ExecutionState.Paused) {
    338 
    339               // start and wait until the alg is started
    340               using (var signal = new ManualResetEvent(false)) {
    341                 EventHandler signalSetter = (sender, args) => { signal.Set(); };
    342                 clonedAlgorithm.Started += signalSetter;
    343                 clonedAlgorithm.Start();
    344                 signal.WaitOne();
    345                 clonedAlgorithm.Started -= signalSetter;
    346 
    347                 startedAlgorithms++;
    348               }
    349             }
     346        OnStarted();
     347      } finally {
     348        if (startPending) startPending = false;
     349      }
     350
     351      availableWorkers = new SemaphoreSlim(NumberOfWorkers.Value, NumberOfWorkers.Value);
     352      allAlgorithmsFinished = new ManualResetEventSlim(false);
     353
     354      //start prepared or paused cloned algorithms
     355      foreach (IAlgorithm clonedAlgorithm in clonedAlgorithms) {
     356        if (pausePending || stopPending || ExecutionState != ExecutionState.Started) break;
     357        if (clonedAlgorithm.ExecutionState == ExecutionState.Prepared ||
     358            clonedAlgorithm.ExecutionState == ExecutionState.Paused) {
     359          availableWorkers.Wait();
     360          lock (locker) {
     361            if (pausePending || stopPending || ExecutionState != ExecutionState.Started) break;
     362            clonedAlgorithm.StartAsync(cancellationToken);
    350363          }
    351364        }
    352         OnStarted();
    353       }
     365      }
     366
     367      allAlgorithmsFinished.Wait();
     368    }
     369
     370    public async Task StartAsync() { await StartAsync(CancellationToken.None); }
     371    public async Task StartAsync(CancellationToken cancellationToken) {
     372      await AsyncHelper.DoAsync(Start, cancellationToken);
    354373    }
    355374
    356375    private bool pausePending;
    357376    public void Pause() {
     377      if (startPending) return;
    358378      if (ExecutionState != ExecutionState.Started)
    359379        throw new InvalidOperationException(string.Format("Pause not allowed in execution state \"{0}\".", ExecutionState));
    360380      if (!pausePending) {
    361381        pausePending = true;
    362         PauseAllClonedAlgorithms();
    363       }
    364     }
    365     private void PauseAllClonedAlgorithms() {
    366       foreach (IAlgorithm clonedAlgorithm in clonedAlgorithms) {
    367         if (clonedAlgorithm.ExecutionState == ExecutionState.Started)
    368           clonedAlgorithm.Pause();
     382        lock (locker) {
     383          var toPause = clonedAlgorithms.Where(x => x.ExecutionState == ExecutionState.Started).ToList();
     384          foreach (var optimizer in toPause) {
     385            // a race-condition may occur when the optimizer has changed the state by itself in the meantime
     386            try { optimizer.Pause(); } catch (InvalidOperationException) { }
     387          }
     388        }
    369389      }
    370390    }
     
    372392    private bool stopPending;
    373393    public void Stop() {
     394      if (startPending) return;
    374395      if ((ExecutionState != ExecutionState.Started) && (ExecutionState != ExecutionState.Paused))
    375396        throw new InvalidOperationException(string.Format("Stop not allowed in execution state \"{0}\".",
     
    377398      if (!stopPending) {
    378399        stopPending = true;
    379         StopAllClonedAlgorithms();
    380       }
    381     }
    382     private void StopAllClonedAlgorithms() {
    383       foreach (IAlgorithm clonedAlgorithm in clonedAlgorithms) {
    384         if (clonedAlgorithm.ExecutionState == ExecutionState.Started ||
    385             clonedAlgorithm.ExecutionState == ExecutionState.Paused)
    386           clonedAlgorithm.Stop();
     400        lock (locker) {
     401          var toStop = clonedAlgorithms.Where(x => x.ExecutionState == ExecutionState.Started || x.ExecutionState == ExecutionState.Paused).ToList();
     402          foreach (var optimizer in toStop) {
     403            // a race-condition may occur when the optimizer has changed the state by itself in the meantime
     404            try { optimizer.Stop(); } catch (InvalidOperationException) { }
     405          }
     406        }
    387407      }
    388408    }
     
    685705    }
    686706    private void ClonedAlgorithm_ExceptionOccurred(object sender, EventArgs<Exception> e) {
     707      Pause();
    687708      OnExceptionOccurred(e.Value);
    688709    }
     
    703724    private void ClonedAlgorithm_Paused(object sender, EventArgs e) {
    704725      lock (locker) {
    705         if (pausePending && clonedAlgorithms.All(alg => alg.ExecutionState != ExecutionState.Started))
     726        availableWorkers.Release();
     727        if (clonedAlgorithms.All(alg => alg.ExecutionState != ExecutionState.Started)) {
    706728          OnPaused();
     729          allAlgorithmsFinished.Set();
     730        }
    707731      }
    708732    }
     
    710734    private void ClonedAlgorithm_Stopped(object sender, EventArgs e) {
    711735      lock (locker) {
    712         if (!stopPending && ExecutionState == ExecutionState.Started) {
    713           IAlgorithm preparedAlgorithm = clonedAlgorithms.FirstOrDefault(alg => alg.ExecutionState == ExecutionState.Prepared ||
    714                                                                                 alg.ExecutionState == ExecutionState.Paused);
    715           if (preparedAlgorithm != null) preparedAlgorithm.Start();
    716         }
    717         if (ExecutionState != ExecutionState.Stopped) {
    718           if (clonedAlgorithms.All(alg => alg.ExecutionState == ExecutionState.Stopped))
    719             OnStopped();
    720           else if (stopPending &&
    721                    clonedAlgorithms.All(
    722                      alg => alg.ExecutionState == ExecutionState.Prepared || alg.ExecutionState == ExecutionState.Stopped))
    723             OnStopped();
     736        // if the algorithm was in paused state, its worker has already been released
     737        if (availableWorkers.CurrentCount < NumberOfWorkers.Value)
     738          availableWorkers.Release();
     739        if (clonedAlgorithms.All(alg => alg.ExecutionState == ExecutionState.Stopped)) {
     740          OnStopped();
     741          allAlgorithmsFinished.Set();
     742        } else if (stopPending && clonedAlgorithms.All(alg => alg.ExecutionState == ExecutionState.Prepared || alg.ExecutionState == ExecutionState.Stopped)) {
     743          OnStopped();
     744          allAlgorithmsFinished.Set();
    724745        }
    725746      }
     
    748769    public event EventHandler Started;
    749770    private void OnStarted() {
     771      startPending = false;
    750772      ExecutionState = ExecutionState.Started;
    751773      EventHandler handler = Started;
  • stable/HeuristicLab.Algorithms.DataAnalysis/3.4/FixedDataAnalysisAlgorithm.cs

    r15061 r15292  
    2121
    2222using System;
     23using System.Linq;
     24using System.Threading;
    2325using HeuristicLab.Common;
    2426using HeuristicLab.Optimization;
Note: See TracChangeset for help on using the changeset viewer.