예제 #1
0
        private void WorkerThreadMethod_NonCaching(object paramObj)
        {
            WorkerThreadInfo info = (WorkerThreadInfo)paramObj;

            for (;;)
            {
                // Wait indefinitely for a signal to wake up and do some work.
                info._awaitWorkEvent.WaitOne();

                // Evaluate the genomes allocated to this worker thread.
                IList <TGenome> genomeList = info._genomeList;
                int             endIdx     = info._endIdx;

                for (int i = info._startIdx; i < endIdx; i++)
                {
                    TGenome  genome  = genomeList[i];
                    TPhenome phenome = _genomeDecoder.Decode(genome);
                    if (null == phenome)
                    {   // Non-viable genome.
                        genome.EvaluationInfo.SetFitness(0.0);
                    }
                    else
                    {
                        double fitness = _phenomeEvaluator.Evaluate(phenome);
                        genome.EvaluationInfo.SetFitness(fitness);
                    }
                }

                // Signal that we have completed the allocated work.
                info._completedWorkEvent.Set();

                // FIXME: What is the proper/clean method of exiting the thread?
            }
        }
예제 #2
0
        public RenderManager(GraphicsDevice device, Thread mainThread)
        {
            if (mainThread == null)
            {
                throw new ArgumentNullException("mainThread");
            }

            MainThread      = mainThread;
            DeviceManager   = new DeviceManager(device);
            _FrameAllocator = new FramePool(this);

            int threadCount = Math.Max(2, Math.Min(8, Environment.ProcessorCount));

            _WorkerInfo = new WorkerThreadInfo[threadCount];
            for (int i = 0; i < threadCount; i++)
            {
                _WorkerInfo[i] = new WorkerThreadInfo();
            }

            _WorkerDelegates = new Action[threadCount];

            for (int i = 0; i < threadCount; i++)
            {
                // Make a copy so that each delegate gets a different value
                int j = i;
                _WorkerDelegates[i] = () =>
                                      WorkerThreadFunc(_WorkerInfo[j]);
            }

            _DisposeResource = DisposeResource;
        }
예제 #3
0
        /// <summary>
        /// Construct with the provided IGenomeDecoder, IPhenomeEvaluator, enablePhenomeCaching flag
        /// and thread count.
        /// </summary>
        /// <param name="genomeDecoder"></param>
        /// <param name="phenomeEvaluator"></param>
        /// <param name="enablePhenomeCaching"></param>
        /// <param name="threadCount"></param>
        public ParallelGenomeListEvaluator(IGenomeDecoder <TGenome, TPhenome> genomeDecoder,
                                           IPhenomeEvaluator <TPhenome> phenomeEvaluator,
                                           bool enablePhenomeCaching,
                                           int threadCount)
        {
            _genomeDecoder        = genomeDecoder;
            _phenomeEvaluator     = phenomeEvaluator;
            _enablePhenomeCaching = enablePhenomeCaching;

            // Determine the appropriate worker-thread method.
            Action <object> workerThreadmethod;

            if (_enablePhenomeCaching)
            {
                workerThreadmethod = WorkerThreadMethod_Caching;
            }
            else
            {
                workerThreadmethod = WorkerThreadMethod_NonCaching;
            }

            _infoArr = new WorkerThreadInfo[threadCount];
            _completedWorkEventArr = new ManualResetEvent[threadCount];
            _threadArr             = new Thread[threadCount];
            for (int i = 0; i < threadCount; i++)
            {
                // Create thread and its own info object.
                WorkerThreadInfo info   = new WorkerThreadInfo();
                Thread           thread = new Thread(new ParameterizedThreadStart(workerThreadmethod));
                thread.IsBackground = true;
                thread.Priority     = ThreadPriority.BelowNormal;

                // Store the thread and it's info object in arrays.
                // Also store references to all of the created _completedWorkEvent objects in an array,
                // this allows to wait for all of them together (WaitHandle.WaitAny/All).
                _threadArr[i]             = thread;
                _infoArr[i]               = info;
                _completedWorkEventArr[i] = info._completedWorkEvent;

                // Start the thread and pass the info object to this invocation of the thread method.
                thread.Start(info);
            }
        }
예제 #4
0
        private void WorkerThreadFunc(WorkerThreadInfo info)
        {
            Frame frame;
            int   start, count;

            lock (info) {
                frame = info.Frame;
                start = info.Start;
                count = info.Count;
            }

            try {
                frame.PrepareSubset(start, count);
            } finally {
                lock (info) {
                    info.Frame = null;
                    info.Start = info.Count = 0;
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Evaluates a list of genomes. Here we decode each genome in using the contained IGenomeDecoder
        /// and evaluate the resulting TPhenome using the contained IPhenomeEvaluator.
        /// </summary>
        /// <param name="genomeList"></param>
        public void Evaluate(IList <TGenome> genomeList)
        {
            // Assign the genome list to all workers.
            int workerCount = _infoArr.Length;

            for (int i = 0; i < workerCount; i++)
            {
                _infoArr[i]._genomeList = genomeList;
            }

            // Determine size of work chunks.
            // Initially we evenly divide the work between workers. Break the work into two chunks per
            // worker to reduce granularity.
            long chunkSize = genomeList.Count / (2 * workerCount);

            if (0L != _prevDuration)
            {   // Try to allocate chunks of no more than 0.5 seconds clock time. This
                // helps prevent some chunks outlasting others by a wide margin (because
                // decode/evaluation time is variable depending on genome size, etc).

                // half-sec chunk size.
                long halfSecChunkSize = (int)((5000000L * genomeList.Count) / _prevDuration);

                // Use the half-sec chunk size if it is smaller than the chunk size calculated by
                // evenly dividing the work.
                chunkSize = Math.Min(chunkSize, halfSecChunkSize);
            }

            // Ensure non-zero chunk size and also cast to a 32bit int.
            int chunkSizeInt = (int)Math.Max(1L, chunkSize);

            // Note the clock tick when we started.
            long startTick = DateTime.Now.Ticks;

            // Allocate work in chunks until all work is completed.
            // Allocate first round of work chunks.
            int genomeIdx   = 0;
            int genomeCount = genomeList.Count;

            for (int i = 0; i < workerCount && genomeIdx < genomeCount; i++)
            {
                // Assign work chunk parameters.
                WorkerThreadInfo info = _infoArr[i];
                info._startIdx = genomeIdx;
                info._endIdx   = genomeIdx = Math.Min(genomeCount, genomeIdx + chunkSizeInt);

                // Reset the completed event as we will be waiting for it. Any that aren't used
                // remain reset (we don't wait for them).
                info._completedWorkEvent.Reset();

                // Signal the worker thread to do the work.
                info._awaitWorkEvent.Set();
            }

            // Keep allocating work chunks to worker threads as they become available and
            // until we run out of available work.
            while (genomeIdx < genomeCount)
            {
                // Wait for a worker thread to signal completion (and therefore become available for more work).
                int idx = WaitHandle.WaitAny(_completedWorkEventArr);

                // Assign new work chunk parameters.
                WorkerThreadInfo info = _infoArr[idx];
                info._startIdx = genomeIdx;
                info._endIdx   = genomeIdx = Math.Min(genomeCount, genomeIdx + chunkSizeInt);

                // Reset the completed event as we will be waiting for it again.
                info._completedWorkEvent.Reset();

                // Signal the worker thread to do the work.
                info._awaitWorkEvent.Set();
            }

            // All work has been allocated. Wait for all worker threads to complete.
            WaitHandle.WaitAll(_completedWorkEventArr);

            // Keep track of how long the evalations took in total clock time.
            _prevDuration = DateTime.Now.Ticks - startTick;

            // Reset the genome list reference in all workers. Cleaning up references helps garbage colelction.
            for (int i = 0; i < workerCount; i++)
            {
                _infoArr[i]._genomeList = null;
            }
        }
예제 #6
0
        protected virtual void OnReceived( ServerSocketAsyncEventArgs e )
        {
            var session = this.GetSession( e.RemoteEndPoint );
            if ( session == null )
            {
                session = this.CreateSession( e.RemoteEndPoint, new ServerSessionContext( e ) );
            }

            var workerThredInfo = new WorkerThreadInfo( DateTime.UtcNow, Thread.CurrentThread );
            if ( !this._exeuctingWorkerThreadTable.TryAdd( Thread.CurrentThread.ManagedThreadId, workerThredInfo ) )
            {
                Environment.FailFast( String.Format( CultureInfo.CurrentCulture, "Startig worker thread {0} is marked running.", Thread.CurrentThread.ManagedThreadId ) );
            }

            try { }
            finally
            {
                if ( Interlocked.Increment( ref this._exeuctingWorkerThreadCount ) == 1 )
                {
                    this._timeoutWatchDog.Change( ( long )this.TimeoutWatchPeriod.TotalMilliseconds, Timeout.Infinite );
                }
            }

            try
            {
                session.Transport.OnReceived( session );
            }
            catch ( ThreadAbortException ex )
            {
                if ( ex.ExceptionState == _executionTimeoutToken )
                {
                    Thread.ResetAbort();
                }
            }
            finally
            {
                if ( Interlocked.Decrement( ref this._exeuctingWorkerThreadCount ) == 0 )
                {
                    this._timeoutWatchDog.Change( Timeout.Infinite, Timeout.Infinite );
                }

                WorkerThreadInfo disposal;
                this._exeuctingWorkerThreadTable.TryRemove( Thread.CurrentThread.ManagedThreadId, out disposal );
                Contract.Assert( disposal.WorkerThread.ManagedThreadId == Thread.CurrentThread.ManagedThreadId );
            }
        }