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? } }
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; }
/// <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); } }
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; } } }
/// <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; } }
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 ); } }