Esempio n. 1
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>
        /// Get an evaluator from the pool.
        /// </summary>
        /// <returns>An evaluator instance.</returns>
        public IPhenomeEvaluator <TPhenome> GetEvaluator()
        {
            bool lockTaken = false;

            try
            {
                // Wait for the sync lock.
                _spinLock.Enter(ref lockTaken);

                // Take an evaluator from the pool (if any available).
                if (_evaluatorStack.Count > 0)
                {
                    return(_evaluatorStack.Pop());
                }
            }
            finally
            {
                // Release the sync lock.
                if (lockTaken)
                {
                    _spinLock.Exit(false);
                }
            }

            // If the pool is empty then create a new evaluator instance; this should get released
            // back into the pool, thus increasing the total number of evaluators being managed by the pool.
            return(_phenomeEvaluationScheme.CreateEvaluator());
        }
        /// <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>
        /// 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);
        }