From 299640ce5f6499e07c5799f48897ac5a77e72c54 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Wed, 18 Jul 2012 01:26:34 -0600 Subject: Persistant multi-threading works perfectly. It uses the forever-blocking variation of the Bu::SynchroQueue dequeue to maximize efficiency. --- src/explicitsimulation.cpp | 64 ++++++++++++++++++++++++++++++++++++---------- src/explicitsimulation.h | 10 +++++--- src/tests/maxima/main.cpp | 2 +- 3 files changed, 59 insertions(+), 17 deletions(-) diff --git a/src/explicitsimulation.cpp b/src/explicitsimulation.cpp index 6a9356b..98df0b0 100644 --- a/src/explicitsimulation.cpp +++ b/src/explicitsimulation.cpp @@ -15,11 +15,11 @@ Genetic::ExplicitSimulation::ExplicitSimulation( Genetic::Operator *pOper, Genetic::FitnessFunction *pFunc, int iThreads, int iPopSize, float fKeep, float fRandom, bool bKeepBest ) : pOper( pOper ), - //pFunc( pFunc ), iPopSize( iPopSize ), fKeep( fKeep ), fRandom( fRandom ), - bKeepBest( bKeepBest ) + bKeepBest( bKeepBest ), + bRunning( true ) { for( int j = 0; j < iPopSize; j++ ) { @@ -35,6 +35,8 @@ Genetic::ExplicitSimulation::ExplicitSimulation( Genetic::Operator *pOper, lProcessor.append( new Processor( *this, pFunc->clone(), qWork, iId++ ) ); + for( ProcessorList::iterator i = lProcessor.begin(); i; i++ ) + (*i)->start(); updateFitness(); } @@ -43,8 +45,9 @@ Genetic::ExplicitSimulation::~ExplicitSimulation() { delete pOper; - for( ProcessorList::iterator i = lProcessor.begin(); i; i++ ) - (*i)->setRunning( false ); + setRunning( false ); + + qWork.unblockAll(); for( ProcessorList::iterator i = lProcessor.begin(); i; i++ ) { (*i)->join(); @@ -139,12 +142,21 @@ void Genetic::ExplicitSimulation::updateFitness() dMinFitness = -1.0; dTotalFitness = 0.0; mFitness.unlock(); + cWorkDone.lock(); + iWorkDone = xPop.getSize(); + cWorkDone.unlock(); for( Population::iterator i = xPop.begin(); i; i++ ) { - if( hFitness.has( i.getKey() ) ) + mFitness.lock(); + bool bHas = hFitness.has( i.getKey() ); + mFitness.unlock(); + if( bHas ) { setFitness( i.getKey(), hFitness.get( i.getKey() ) ); + cWorkDone.lock(); + iWorkDone--; + cWorkDone.unlock(); } else { @@ -152,11 +164,16 @@ void Genetic::ExplicitSimulation::updateFitness() } } - for( ProcessorList::iterator i = lProcessor.begin(); i; i++ ) - (*i)->start(); + cWorkDone.lock(); + if( iWorkDone == 0 ) + { + cWorkDone.unlock(); + return; + } - for( ProcessorList::iterator i = lProcessor.begin(); i; i++ ) - (*i)->join(); + while( iWorkDone > 0 ) + cWorkDone.wait(); + cWorkDone.unlock(); } void Genetic::ExplicitSimulation::setFitness( Genetic::PhenotypeId id, @@ -166,7 +183,6 @@ void Genetic::ExplicitSimulation::setFitness( Genetic::PhenotypeId id, if( dFitness < 0.0 ) dFitness = 0.0; -// sio << id << ": " << dFitness << sio.nl; hFitness.insert( id, dFitness ); dTotalFitness += dFitness; @@ -186,6 +202,28 @@ void Genetic::ExplicitSimulation::setFitness( Genetic::PhenotypeId id, } } +void Genetic::ExplicitSimulation::workDone() +{ + cWorkDone.lock(); + iWorkDone--; + + if( iWorkDone == 0 ) + cWorkDone.signal(); + cWorkDone.unlock(); +} + +void Genetic::ExplicitSimulation::setRunning( bool b ) +{ + Bu::MutexLocker ml( mRunning ); + bRunning = b; +} + +bool Genetic::ExplicitSimulation::isRunning() +{ + Bu::MutexLocker ml( mRunning ); + return bRunning; +} + Genetic::ExplicitSimulation::Processor::Processor( Genetic::ExplicitSimulation &rSim, Genetic::FitnessFunction *pFunc, @@ -205,15 +243,15 @@ Genetic::ExplicitSimulation::Processor::~Processor() void Genetic::ExplicitSimulation::Processor::run() { - bRunning = true; - while( bRunning && !rqWork.isEmpty() ) + while( rSim.isRunning() ) { - Genetic::Phenotype *pPhen = rqWork.dequeue( 0, 250000 ); + Genetic::Phenotype *pPhen = rqWork.dequeue( true ); if( pPhen == NULL ) continue; double dFitness = (*pFunc)( pPhen ); rSim.setFitness( pPhen->getId(), dFitness ); + rSim.workDone(); } } diff --git a/src/explicitsimulation.h b/src/explicitsimulation.h index c2aeed9..7713c71 100644 --- a/src/explicitsimulation.h +++ b/src/explicitsimulation.h @@ -31,6 +31,9 @@ namespace Genetic protected: void updateFitness(); void setFitness( Genetic::PhenotypeId, double dFitness ); + void workDone(); + void setRunning( bool b ); + bool isRunning(); protected: Population xPop; @@ -49,8 +52,12 @@ namespace Genetic PhenotypeId uMaxFitness; Bu::Mutex mFitness; + Bu::Condition cWorkDone; typedef Bu::SynchroQueue WorkQueue; WorkQueue qWork; + int iWorkDone; + bool bRunning; + Bu::Mutex mRunning; class Processor : public Bu::Thread { @@ -59,8 +66,6 @@ namespace Genetic WorkQueue &rqWork, int iId ); virtual ~Processor(); - void setRunning( bool b ) { bRunning = b; } - protected: virtual void run(); @@ -68,7 +73,6 @@ namespace Genetic FitnessFunction *pFunc; WorkQueue &rqWork; int iId; - bool bRunning; }; typedef Bu::List ProcessorList; diff --git a/src/tests/maxima/main.cpp b/src/tests/maxima/main.cpp index db11f66..176a589 100644 --- a/src/tests/maxima/main.cpp +++ b/src/tests/maxima/main.cpp @@ -14,7 +14,7 @@ int main( int argc, char *argv[] ) { Bu::Random::seed( time( NULL ) ); sio << "Global maxima equation test" << sio.nl - << " - -1.8*x^4 + 0.86*x^3 + 4.0*x^2 == 3.53518 (approx)" << sio.nl + << " -1.8*x^4 + 0.86*x^3 + 4.0*x^2 == 3.53518 (approx)" << sio.nl << sio.nl; Genetic::ExplicitSimulation ex( -- cgit v1.2.3