diff options
author | Mike Buland <mike@xagasoft.com> | 2012-07-18 01:26:34 -0600 |
---|---|---|
committer | Mike Buland <mike@xagasoft.com> | 2012-07-18 01:26:34 -0600 |
commit | 299640ce5f6499e07c5799f48897ac5a77e72c54 (patch) | |
tree | 47b502fca70dc2fc8a48ae9b3ae813763e98c78e | |
parent | a2679e3bc2f407fae6b97908aeebb215c6678ebc (diff) | |
download | libgenetic-299640ce5f6499e07c5799f48897ac5a77e72c54.tar.gz libgenetic-299640ce5f6499e07c5799f48897ac5a77e72c54.tar.bz2 libgenetic-299640ce5f6499e07c5799f48897ac5a77e72c54.tar.xz libgenetic-299640ce5f6499e07c5799f48897ac5a77e72c54.zip |
Persistant multi-threading works perfectly.
It uses the forever-blocking variation of the Bu::SynchroQueue dequeue
to maximize efficiency.
-rw-r--r-- | src/explicitsimulation.cpp | 64 | ||||
-rw-r--r-- | src/explicitsimulation.h | 10 | ||||
-rw-r--r-- | 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, | |||
15 | Genetic::FitnessFunction *pFunc, int iThreads, int iPopSize, | 15 | Genetic::FitnessFunction *pFunc, int iThreads, int iPopSize, |
16 | float fKeep, float fRandom, bool bKeepBest ) : | 16 | float fKeep, float fRandom, bool bKeepBest ) : |
17 | pOper( pOper ), | 17 | pOper( pOper ), |
18 | //pFunc( pFunc ), | ||
19 | iPopSize( iPopSize ), | 18 | iPopSize( iPopSize ), |
20 | fKeep( fKeep ), | 19 | fKeep( fKeep ), |
21 | fRandom( fRandom ), | 20 | fRandom( fRandom ), |
22 | bKeepBest( bKeepBest ) | 21 | bKeepBest( bKeepBest ), |
22 | bRunning( true ) | ||
23 | { | 23 | { |
24 | for( int j = 0; j < iPopSize; j++ ) | 24 | for( int j = 0; j < iPopSize; j++ ) |
25 | { | 25 | { |
@@ -35,6 +35,8 @@ Genetic::ExplicitSimulation::ExplicitSimulation( Genetic::Operator *pOper, | |||
35 | lProcessor.append( | 35 | lProcessor.append( |
36 | new Processor( *this, pFunc->clone(), qWork, iId++ ) | 36 | new Processor( *this, pFunc->clone(), qWork, iId++ ) |
37 | ); | 37 | ); |
38 | for( ProcessorList::iterator i = lProcessor.begin(); i; i++ ) | ||
39 | (*i)->start(); | ||
38 | 40 | ||
39 | updateFitness(); | 41 | updateFitness(); |
40 | } | 42 | } |
@@ -43,8 +45,9 @@ Genetic::ExplicitSimulation::~ExplicitSimulation() | |||
43 | { | 45 | { |
44 | delete pOper; | 46 | delete pOper; |
45 | 47 | ||
46 | for( ProcessorList::iterator i = lProcessor.begin(); i; i++ ) | 48 | setRunning( false ); |
47 | (*i)->setRunning( false ); | 49 | |
50 | qWork.unblockAll(); | ||
48 | for( ProcessorList::iterator i = lProcessor.begin(); i; i++ ) | 51 | for( ProcessorList::iterator i = lProcessor.begin(); i; i++ ) |
49 | { | 52 | { |
50 | (*i)->join(); | 53 | (*i)->join(); |
@@ -139,12 +142,21 @@ void Genetic::ExplicitSimulation::updateFitness() | |||
139 | dMinFitness = -1.0; | 142 | dMinFitness = -1.0; |
140 | dTotalFitness = 0.0; | 143 | dTotalFitness = 0.0; |
141 | mFitness.unlock(); | 144 | mFitness.unlock(); |
145 | cWorkDone.lock(); | ||
146 | iWorkDone = xPop.getSize(); | ||
147 | cWorkDone.unlock(); | ||
142 | 148 | ||
143 | for( Population::iterator i = xPop.begin(); i; i++ ) | 149 | for( Population::iterator i = xPop.begin(); i; i++ ) |
144 | { | 150 | { |
145 | if( hFitness.has( i.getKey() ) ) | 151 | mFitness.lock(); |
152 | bool bHas = hFitness.has( i.getKey() ); | ||
153 | mFitness.unlock(); | ||
154 | if( bHas ) | ||
146 | { | 155 | { |
147 | setFitness( i.getKey(), hFitness.get( i.getKey() ) ); | 156 | setFitness( i.getKey(), hFitness.get( i.getKey() ) ); |
157 | cWorkDone.lock(); | ||
158 | iWorkDone--; | ||
159 | cWorkDone.unlock(); | ||
148 | } | 160 | } |
149 | else | 161 | else |
150 | { | 162 | { |
@@ -152,11 +164,16 @@ void Genetic::ExplicitSimulation::updateFitness() | |||
152 | } | 164 | } |
153 | } | 165 | } |
154 | 166 | ||
155 | for( ProcessorList::iterator i = lProcessor.begin(); i; i++ ) | 167 | cWorkDone.lock(); |
156 | (*i)->start(); | 168 | if( iWorkDone == 0 ) |
169 | { | ||
170 | cWorkDone.unlock(); | ||
171 | return; | ||
172 | } | ||
157 | 173 | ||
158 | for( ProcessorList::iterator i = lProcessor.begin(); i; i++ ) | 174 | while( iWorkDone > 0 ) |
159 | (*i)->join(); | 175 | cWorkDone.wait(); |
176 | cWorkDone.unlock(); | ||
160 | } | 177 | } |
161 | 178 | ||
162 | void Genetic::ExplicitSimulation::setFitness( Genetic::PhenotypeId id, | 179 | void Genetic::ExplicitSimulation::setFitness( Genetic::PhenotypeId id, |
@@ -166,7 +183,6 @@ void Genetic::ExplicitSimulation::setFitness( Genetic::PhenotypeId id, | |||
166 | if( dFitness < 0.0 ) | 183 | if( dFitness < 0.0 ) |
167 | dFitness = 0.0; | 184 | dFitness = 0.0; |
168 | 185 | ||
169 | // sio << id << ": " << dFitness << sio.nl; | ||
170 | hFitness.insert( id, dFitness ); | 186 | hFitness.insert( id, dFitness ); |
171 | 187 | ||
172 | dTotalFitness += dFitness; | 188 | dTotalFitness += dFitness; |
@@ -186,6 +202,28 @@ void Genetic::ExplicitSimulation::setFitness( Genetic::PhenotypeId id, | |||
186 | } | 202 | } |
187 | } | 203 | } |
188 | 204 | ||
205 | void Genetic::ExplicitSimulation::workDone() | ||
206 | { | ||
207 | cWorkDone.lock(); | ||
208 | iWorkDone--; | ||
209 | |||
210 | if( iWorkDone == 0 ) | ||
211 | cWorkDone.signal(); | ||
212 | cWorkDone.unlock(); | ||
213 | } | ||
214 | |||
215 | void Genetic::ExplicitSimulation::setRunning( bool b ) | ||
216 | { | ||
217 | Bu::MutexLocker ml( mRunning ); | ||
218 | bRunning = b; | ||
219 | } | ||
220 | |||
221 | bool Genetic::ExplicitSimulation::isRunning() | ||
222 | { | ||
223 | Bu::MutexLocker ml( mRunning ); | ||
224 | return bRunning; | ||
225 | } | ||
226 | |||
189 | Genetic::ExplicitSimulation::Processor::Processor( | 227 | Genetic::ExplicitSimulation::Processor::Processor( |
190 | Genetic::ExplicitSimulation &rSim, | 228 | Genetic::ExplicitSimulation &rSim, |
191 | Genetic::FitnessFunction *pFunc, | 229 | Genetic::FitnessFunction *pFunc, |
@@ -205,15 +243,15 @@ Genetic::ExplicitSimulation::Processor::~Processor() | |||
205 | 243 | ||
206 | void Genetic::ExplicitSimulation::Processor::run() | 244 | void Genetic::ExplicitSimulation::Processor::run() |
207 | { | 245 | { |
208 | bRunning = true; | 246 | while( rSim.isRunning() ) |
209 | while( bRunning && !rqWork.isEmpty() ) | ||
210 | { | 247 | { |
211 | Genetic::Phenotype *pPhen = rqWork.dequeue( 0, 250000 ); | 248 | Genetic::Phenotype *pPhen = rqWork.dequeue( true ); |
212 | if( pPhen == NULL ) | 249 | if( pPhen == NULL ) |
213 | continue; | 250 | continue; |
214 | 251 | ||
215 | double dFitness = (*pFunc)( pPhen ); | 252 | double dFitness = (*pFunc)( pPhen ); |
216 | rSim.setFitness( pPhen->getId(), dFitness ); | 253 | rSim.setFitness( pPhen->getId(), dFitness ); |
254 | rSim.workDone(); | ||
217 | } | 255 | } |
218 | } | 256 | } |
219 | 257 | ||
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 | |||
31 | protected: | 31 | protected: |
32 | void updateFitness(); | 32 | void updateFitness(); |
33 | void setFitness( Genetic::PhenotypeId, double dFitness ); | 33 | void setFitness( Genetic::PhenotypeId, double dFitness ); |
34 | void workDone(); | ||
35 | void setRunning( bool b ); | ||
36 | bool isRunning(); | ||
34 | 37 | ||
35 | protected: | 38 | protected: |
36 | Population xPop; | 39 | Population xPop; |
@@ -49,8 +52,12 @@ namespace Genetic | |||
49 | PhenotypeId uMaxFitness; | 52 | PhenotypeId uMaxFitness; |
50 | 53 | ||
51 | Bu::Mutex mFitness; | 54 | Bu::Mutex mFitness; |
55 | Bu::Condition cWorkDone; | ||
52 | typedef Bu::SynchroQueue<Phenotype *> WorkQueue; | 56 | typedef Bu::SynchroQueue<Phenotype *> WorkQueue; |
53 | WorkQueue qWork; | 57 | WorkQueue qWork; |
58 | int iWorkDone; | ||
59 | bool bRunning; | ||
60 | Bu::Mutex mRunning; | ||
54 | 61 | ||
55 | class Processor : public Bu::Thread | 62 | class Processor : public Bu::Thread |
56 | { | 63 | { |
@@ -59,8 +66,6 @@ namespace Genetic | |||
59 | WorkQueue &rqWork, int iId ); | 66 | WorkQueue &rqWork, int iId ); |
60 | virtual ~Processor(); | 67 | virtual ~Processor(); |
61 | 68 | ||
62 | void setRunning( bool b ) { bRunning = b; } | ||
63 | |||
64 | protected: | 69 | protected: |
65 | virtual void run(); | 70 | virtual void run(); |
66 | 71 | ||
@@ -68,7 +73,6 @@ namespace Genetic | |||
68 | FitnessFunction *pFunc; | 73 | FitnessFunction *pFunc; |
69 | WorkQueue &rqWork; | 74 | WorkQueue &rqWork; |
70 | int iId; | 75 | int iId; |
71 | bool bRunning; | ||
72 | }; | 76 | }; |
73 | 77 | ||
74 | typedef Bu::List<Processor *> ProcessorList; | 78 | typedef Bu::List<Processor *> 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[] ) | |||
14 | { | 14 | { |
15 | Bu::Random::seed( time( NULL ) ); | 15 | Bu::Random::seed( time( NULL ) ); |
16 | sio << "Global maxima equation test" << sio.nl | 16 | sio << "Global maxima equation test" << sio.nl |
17 | << " - -1.8*x^4 + 0.86*x^3 + 4.0*x^2 == 3.53518 (approx)" << sio.nl | 17 | << " -1.8*x^4 + 0.86*x^3 + 4.0*x^2 == 3.53518 (approx)" << sio.nl |
18 | << sio.nl; | 18 | << sio.nl; |
19 | 19 | ||
20 | Genetic::ExplicitSimulation ex( | 20 | Genetic::ExplicitSimulation ex( |