/// <summary> /// Create a new genome list evaluator. /// </summary> /// <typeparam name="TGenome">Genome type.</typeparam> /// <typeparam name="TPhenome">Phenome type.</typeparam> /// <param name="genomeDecoder">Genome decoder, for decoding a genome to a phenome.</param> /// <param name="phenomeEvaluationScheme">Phenome evaluation scheme.</param> /// <param name="degreeOfParallelism">The number of CPU threads to distribute work to.</param> /// <returns>A new instance of <see cref="IGenomeListEvaluator{TGenome}"/>.</returns> public static IGenomeListEvaluator <TGenome> CreateEvaluator <TGenome, TPhenome>( IGenomeDecoder <TGenome, TPhenome> genomeDecoder, IPhenomeEvaluationScheme <TPhenome> phenomeEvaluationScheme, int degreeOfParallelism) where TGenome : IGenome where TPhenome : class, IDisposable { // Reject nonsensical values for degreeOfParallelism. if (degreeOfParallelism < 1) { throw new ArgumentException(nameof(degreeOfParallelism)); } // Create a serial (single threaded) evaluator if degreeOfParallelism is one. if (degreeOfParallelism == 1) { return(new SerialGenomeListEvaluator <TGenome, TPhenome>(genomeDecoder, phenomeEvaluationScheme)); } // Create a parallel (multi-threaded) evaluator for degreeOfParallelism > 1. if (phenomeEvaluationScheme.EvaluatorsHaveState) { return(new ParallelGenomeListEvaluator <TGenome, TPhenome>(genomeDecoder, phenomeEvaluationScheme, degreeOfParallelism)); } // else return(new ParallelGenomeListEvaluatorStateless <TGenome, TPhenome>(genomeDecoder, phenomeEvaluationScheme, degreeOfParallelism)); }
/// <summary> /// Construct with the provided genome decoder and phenome evaluator. /// </summary> /// <param name="genomeDecoder">Genome decoder.</param> /// <param name="phenomeEvaluationScheme">Phenome evaluation scheme.</param> /// <param name="degreeOfParallelism">The desired degree of parallelism.</param> public ParallelGenomeListEvaluator( IGenomeDecoder <TGenome, TPhenome> genomeDecoder, IPhenomeEvaluationScheme <TPhenome> phenomeEvaluationScheme, int degreeOfParallelism) { // This class should only be used with evaluation schemes that use evaluators with state, // otherwise ParallelGenomeListEvaluatorStateless should be used. if (!phenomeEvaluationScheme.EvaluatorsHaveState) { throw new ArgumentException(nameof(phenomeEvaluationScheme)); } // Reject degreeOfParallelism values less than 2. -1 should have been resolved to an actual number by the time // this constructor is invoked, and 1 is nonsensical for a parallel evaluator. if (degreeOfParallelism < 2) { throw new ArgumentException(nameof(degreeOfParallelism)); } _genomeDecoder = genomeDecoder; _phenomeEvaluationScheme = phenomeEvaluationScheme; _parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = degreeOfParallelism }; // Create a pool of phenome evaluators. // Note. the pool is initialised with a number of pre-constructed evaluators that matches // degreeOfParallelism. We don't expect the pool to be asked for more than this number of // evaluators at any given point in time. _evaluatorPool = new PhenomeEvaluatorStackPool <TPhenome>( phenomeEvaluationScheme, degreeOfParallelism); }
/// <summary> /// Construct with the provided IGenomeDecoder, IPhenomeEvaluator and ParallelOptions. /// </summary> public ParallelGenomeListEvaluator( IGenomeDecoder <TGenome, TPhenome> genomeDecoder, IPhenomeEvaluationScheme <TPhenome> phenomeEvaluatorScheme, ParallelOptions parallelOptions) { // This class should only be used with evaluation schemes that use evaluators with state, // otherwise ParallelGenomeListEvaluatorStateless should be used. if (!phenomeEvaluatorScheme.EvaluatorsHaveState) { throw new ArgumentException(nameof(phenomeEvaluatorScheme)); } _genomeDecoder = genomeDecoder; _phenomeEvaluationScheme = phenomeEvaluatorScheme; _parallelOptions = parallelOptions; // Resolve concurrency level. int concurrencyLevel = parallelOptions.MaxDegreeOfParallelism; if (concurrencyLevel == -1) { concurrencyLevel = Environment.ProcessorCount; } // Create a pool of phenome evaluators. // Note. the pool is initialised with a number of pre-constructed evaluators that matches // MaxDegreeOfParallelism. We don't expect the pool to be asked for more than this number of // evaluators at any given point in time. _evaluatorPool = new PhenomeEvaluatorStackPool <TPhenome>( phenomeEvaluatorScheme, concurrencyLevel); }
/// <summary> /// Construct with the provided genome decoder and phenome evaluator. /// </summary> /// <param name="genomeDecoder">Genome decoder.</param> /// <param name="phenomeEvaluationScheme">Phenome evaluation scheme.</param> /// <param name="degreeOfParallelism">The desired degree of parallelism.</param> public ParallelGenomeListEvaluatorStateless( IGenomeDecoder <TGenome, TPhenome> genomeDecoder, IPhenomeEvaluationScheme <TPhenome> phenomeEvaluationScheme, int degreeOfParallelism) { // This class can only accept an evaluation scheme that uses a stateless evaluator. if (phenomeEvaluationScheme.EvaluatorsHaveState) { throw new ArgumentException(nameof(phenomeEvaluationScheme)); } // Reject degreeOfParallelism values less than 2. -1 should have been resolved to an actual number by the time // this constructor is invoked, and 1 is nonsensical for a parallel evaluator. if (degreeOfParallelism < 2) { throw new ArgumentException(nameof(degreeOfParallelism)); } _genomeDecoder = genomeDecoder; _phenomeEvaluationScheme = phenomeEvaluationScheme; _phenomeEvaluator = phenomeEvaluationScheme.CreateEvaluator(); _parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = degreeOfParallelism }; }
/// <summary> /// Construct with the provided <see cref="IGenomeDecoder{TGenome,TPhenome}"/> and <see cref="IPhenomeEvaluator{TPhenome}"/>. /// Phenome caching is enabled by default. /// </summary> public SerialGenomeListEvaluator( IGenomeDecoder <TGenome, TPhenome> genomeDecoder, IPhenomeEvaluationScheme <TPhenome> phenomeEvaluationScheme) { _genomeDecoder = genomeDecoder; _phenomeEvaluationScheme = phenomeEvaluationScheme; // Note. SerialGenomeListEvaluator will only evaluate on one thread therefore only ever requires a single evaluator. _phenomeEvaluator = phenomeEvaluationScheme.CreateEvaluator(); }
/// <summary> /// Construct with the provided IGenomeDecoder, IPhenomeEvaluator and ParallelOptions. /// </summary> public ParallelGenomeListEvaluatorStateless( IGenomeDecoder <TGenome, TPhenome> genomeDecoder, IPhenomeEvaluationScheme <TPhenome> phenomeEvaluatorScheme, ParallelOptions parallelOptions) { // This class can only accept an evaluation scheme that uses a stateless evaluator. if (phenomeEvaluatorScheme.EvaluatorsHaveState) { throw new ArgumentException(nameof(phenomeEvaluatorScheme)); } _genomeDecoder = genomeDecoder; _phenomeEvaluationScheme = phenomeEvaluatorScheme; _phenomeEvaluator = phenomeEvaluatorScheme.CreateEvaluator(); _parallelOptions = parallelOptions; }
/// <summary> /// Create a new genome list evaluator. /// </summary> /// <typeparam name="TGenome">Genome type.</typeparam> /// <typeparam name="TPhenome">Phenome type.</typeparam> /// <param name="genomeDecoder">Genome decoder, for decoding a genome to a phenome.</param> /// <param name="phenomeEvaluationScheme">Phenome evaluation scheme.</param> /// <param name="createConcurrentEvaluator">If true a evaluator that runs on multiple threads will be created.</param> /// <returns>A new instance of <see cref="IGenomeListEvaluator{TGenome}"/></returns> public static IGenomeListEvaluator <TGenome> CreateEvaluator <TGenome, TPhenome>( IGenomeDecoder <TGenome, TPhenome> genomeDecoder, IPhenomeEvaluationScheme <TPhenome> phenomeEvaluationScheme, bool createConcurrentEvaluator) where TGenome : IGenome where TPhenome : class { if (!createConcurrentEvaluator) { return(new SerialGenomeListEvaluator <TGenome, TPhenome>(genomeDecoder, phenomeEvaluationScheme)); } // Create a parallelised evaluator. if (phenomeEvaluationScheme.EvaluatorsHaveState) { return(new ParallelGenomeListEvaluator <TGenome, TPhenome>(genomeDecoder, phenomeEvaluationScheme)); } // else return(new ParallelGenomeListEvaluatorStateless <TGenome, TPhenome>(genomeDecoder, phenomeEvaluationScheme)); }
/// <summary> /// Construct a new instance. /// </summary> /// <param name="phenomeEvaluationScheme">Phenome evaluation scheme.</param> /// <param name="initialPoolSize">Initial pool size.</param> public PhenomeEvaluatorStackPool( IPhenomeEvaluationScheme <TPhenome> phenomeEvaluationScheme, int initialPoolSize) { if (!phenomeEvaluationScheme.EvaluatorsHaveState) { throw new InvalidOperationException("A stateless evaluation scheme does not require an evaluator pool; just use a single evaluator instance concurrently."); } _phenomeEvaluationScheme = phenomeEvaluationScheme; // Create the stack with the spare capacity; to avoid re-alloc overhead if we require additional capacity. _evaluatorStack = new LightweightStack <IPhenomeEvaluator <TPhenome> >(initialPoolSize * 2); // Pre-populate with evaluators. for (int i = 0; i < initialPoolSize; i++) { _evaluatorStack.Push(phenomeEvaluationScheme.CreateEvaluator()); } // Enable thread tracking only if the debugger is attached; it adds non-trivial overhead to Enter/Exit. _spinLock = new SpinLock(Debugger.IsAttached); }
/// <summary> /// Construct with the provided IGenomeDecoder and IPhenomeEvaluator. /// </summary> public ParallelGenomeListEvaluatorStateless( IGenomeDecoder <TGenome, TPhenome> genomeDecoder, IPhenomeEvaluationScheme <TPhenome> phenomeEvaluationScheme) : this(genomeDecoder, phenomeEvaluationScheme, new ParallelOptions()) { }