/// <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));
        }
예제 #2
0
        /// <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);
        }
예제 #3
0
        /// <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);
        }
예제 #4
0
        /// <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;
        }
예제 #7
0
        /// <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())
 {
 }