void ParallelEvaluation(IEvolutionState state, ISimpleProblem prob, SimpleEvaluator evaluator) { // BRS: TPL DataFlow is cleaner and safer than using raw threads. // Limit the concurrency in case the user has gone overboard! var maxDegree = Math.Min(Environment.ProcessorCount, state.EvalThreads); var options = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = maxDegree }; Action <SimpleEvaluatorThread> act = t => t.Run(); var actionBlock = new ActionBlock <SimpleEvaluatorThread>(act, options); for (var i = 0; i < state.EvalThreads; i++) { var runnable = new SimpleEvaluatorThread { ThreadNum = i, State = state, Problem = (ISimpleProblem)prob.Clone(), Evaluator = evaluator, }; actionBlock.Post(runnable); } actionBlock.Complete(); actionBlock.Completion.Wait(); }
public ECTaskArgs(IEvolutionState state, ISimpleProblem problem, Individual ind, int subpopIndex, int threadNum) { State = state; Problem = problem; Individual = ind; SubpopIndex = subpopIndex; ThreadNum = threadNum; //problem.Evaluate(state, ind, subpopIndex, threadNum); }
/** * For each of the iteration, we are not just evaluate the individuals in * current population but also current best individual and individuals in * activeSolutions. Their number of evaluation is determined by there * fitness statistics. */ protected override void EvalPopChunk(IEvolutionState state, int[] numinds, int[] from, int threadnum, ISimpleProblem p) { // so far the evaluator only support when evalthread is 1 ((Problem)p).PrepareToEvaluate(state, threadnum); IList <Subpopulation> subpops = state.Population.Subpops; int len = subpops.Count; for (int pop = 0; pop < len; pop++) { // start evaluatin'! int fp = from[pop]; int upperbound = fp + numinds[pop]; IList <Individual> inds = subpops[pop].Individuals; if (subpops[pop].Species is DOVSSpecies) { var species = (DOVSSpecies)subpops[pop].Species; // Evaluator need to evaluate individual from two set: Sk // (individuals) and activeSolution // Original comment: To avoid unnecessary complication with // stopping test // procedure, require that Sk has at least 2 reps. // Although we do not have stopping test here, we still do 2 // reps foreach (Individual ind in inds) { var fit = (DOVSFitness)ind.Fitness; int addrep = 2 - fit.NumOfObservations; for (int rep = 0; rep < addrep; ++rep) { p.Evaluate(state, ind, pop, threadnum); species.NumOfTotalSamples++; } } // This is a special treat for activeSolutions when // certain criteria have met if ( //species.ocba && species.Stochastic) { // ocba only makes sense when it is a stoc simulation // allocate some reps to active solutions and sample // best according to an ocba like heuristic // if ocba option is turned on. // There are deltan more reps to allocate, where deltan // = sizeof(activesolutions). int deltan = species.ActiveSolutions.Count; // Always add two more reps to current sample best for (int i = 0; i < 2; i++) { p.Evaluate(state, species.Visited[species.OptimalIndex], pop, threadnum); } species.NumOfTotalSamples += 2; deltan -= 2; if (deltan > 0) { // get R double R = 0; foreach (Individual ind in species.ActiveSolutions) { var fit = (DOVSFitness)ind.Fitness; Individual bestInd = species.Visited[species.OptimalIndex]; var bestFit = (DOVSFitness)bestInd.Fitness; R += (fit.Variance / Math.Max(1e-10, Math.Abs(fit.Mean - bestFit.Mean))); } foreach (Individual ind in species.ActiveSolutions) { var fit = (DOVSFitness)ind.Fitness; Individual bestInd = species.Visited[species.OptimalIndex]; var bestFit = (DOVSFitness)bestInd.Fitness; double fraction = fit.Variance / Math.Max(1e-10, Math.Abs(fit.Mean - bestFit.Mean)) / R; double tempDeltan = fraction * deltan; if (tempDeltan > 1) { long roundedDeltan = (long)tempDeltan; for (int j = 0; j < roundedDeltan; ++j) { p.Evaluate(state, ind, pop, threadnum); } species.NumOfTotalSamples += roundedDeltan; } } } } // If it is a deterministic simulation, only one rep // origial code start generation at 1, we start at 0 // thus, we add 1 to computation of base of log int baseGen = state.Generation + 1; int newReps = (int)Math .Ceiling(species.InitialReps * Math.Max(1, Math.Pow(Math.Log((double)baseGen / 2), 1.01))); if (species.Stochastic) { species.Repetition = (species.Repetition >= newReps) ? species.Repetition : newReps; } else { species.Repetition = 1; } // Now do the simulations for activeSolutions foreach (Individual ind in species.ActiveSolutions) { var fit = (DOVSFitness)ind.Fitness; if (fit.NumOfObservations < species.Repetition) { int newrep = species.Repetition - fit.NumOfObservations; for (int rep = 0; rep < newrep; ++rep) { p.Evaluate(state, ind, pop, threadnum); } species.NumOfTotalSamples += newrep; } } // Simulate current sample best { Individual bestIndividual = species.Visited[species.OptimalIndex]; var fit = (DOVSFitness)(bestIndividual.Fitness); if (fit.NumOfObservations < species.Repetition) { int newrep = species.Repetition - fit.NumOfObservations; for (int rep = 0; rep < newrep; ++rep) { p.Evaluate(state, bestIndividual, pop, threadnum); } species.NumOfTotalSamples += newrep; } } // Simulate current individuals // Since backtracking flag is always false, we always do this foreach (Individual ind in inds) { var fit = (DOVSFitness)ind.Fitness; if (fit.NumOfObservations < species.Repetition) { int newRep = species.Repetition - fit.NumOfObservations; for (int rep = 0; rep < newRep; ++rep) { p.Evaluate(state, ind, pop, threadnum); } species.NumOfTotalSamples += newRep; } } } else { for (int x = fp; x < upperbound; x++) { p.Evaluate(state, inds[x], pop, threadnum); } } } ((Problem)p).FinishEvaluating(state, threadnum); }
/// <summary> /// A private helper function for evaluatePopulation which evaluates a chunk /// of individuals in a subpop for a given thread. /// Although this method is declared /// protected, you should not call it. /// </summary> protected virtual void EvalPopChunk(IEvolutionState state, int[] numinds, int[] from, int threadnum, ISimpleProblem p) { p.PrepareToEvaluate(state, threadnum); var subpops = state.Population.Subpops; var len = subpops.Count; for (var pop = 0; pop < len; pop++) { // start evaluatin'! var fp = from[pop]; var upperbound = fp + numinds[pop]; var inds = subpops[pop].Individuals; for (var x = fp; x < upperbound; x++) { p.Evaluate(state, inds[x], pop, threadnum); } state.IncrementEvaluations(upperbound - fp); } p.FinishEvaluating(state, threadnum); }
private static void EvaluateSimpleProblemCore(IEvolutionState state, bool returnIndividuals, BinaryReader dataIn, BinaryWriter dataOut, int numInds, int[] subpops) { // TODO: Refactor this to use TPL DataFlow! var problems = new ISimpleProblem[numInds]; var updateFitness = new bool[numInds]; var inds = new Individual[numInds]; var indForThread = new int[numInds]; try { // BRS: TPL DataFlow BEGIN var maxDegree = Math.Min(Environment.ProcessorCount, state.EvalThreads); var options = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = maxDegree }; var block = new TransformBlock <SlaveEvalThread, Individual>(eval => { eval.Run(); return(eval.Ind); }, options); for (var i = 0; i < numInds; i++) { var ind = state.Population.Subpops[subpops[i]].Species.NewIndividual(state, dataIn); if (problems[i] == null) { problems[i] = (ISimpleProblem)state.Evaluator.p_problem.Clone(); } updateFitness[i] = dataIn.ReadBoolean(); var runnable = new SlaveEvalThread { ThreadNum = i, State = state, Problem = problems[i], Ind = ind, Subpop = subpops[i] }; block.Post(runnable); } for (var i = 0; i < numInds; i++) { // This preserves the original block posting order so we can just use the index. var ind = block.Receive(); // Return the evaluated Individual by index... ReturnIndividualsToMaster(state, inds, updateFitness, dataOut, returnIndividuals, individualInQuestion: i); // return just that individual } // BRS: TPL DataFlow END } catch (IOException e) { state.Output.Fatal("Unable to read individual from master." + e); } // gather everyone for (var i = 0; i < numInds; i++) { ReturnIndividualsToMaster(state, inds, updateFitness, dataOut, returnIndividuals, indForThread[i]); // return just that individual } try { dataOut.Flush(); } catch (IOException e) { state.Output.Fatal("Caught fatal IOException\n" + e); } }