00001 /* 00002 * This file is part of openMask © INRIA, CNRS, Universite de Rennes 1 1993-2002, thereinafter the Software 00003 * 00004 * The Software has been developped within the Siames Project. 00005 * INRIA, the University of Rennes 1 and CNRS jointly hold intellectual property rights 00006 * 00007 * The Software has been registered with the Agence pour la Protection des 00008 * Programmes (APP) under registration number IDDN.FR.001.510008.00.S.P.2001.000.41200 00009 * 00010 * This file may be distributed under the terms of the Q Public License 00011 * version 1.0 as defined by Trolltech AS of Norway and appearing in the file 00012 * LICENSE.QPL included in the packaging of this file. 00013 * 00014 * Licensees holding valid specific licenses issued by INRIA, CNRS or Université de Rennes 1 00015 * for the software may use this file in accordance with that specific license 00016 * 00017 */ 00018 #include "PsnMultiThreadedBenchmarkingScheduler.h" 00019 00020 #include "PsnFrameScheduler.h" 00021 #include "PsnBenchScheduler.h" 00022 #include "PsnBarrier.h" 00023 #include "PsController.h" 00024 #include "PsDuplicatedObject.h" 00025 00026 #include "PsnNew.h" 00027 #include "PsnDescriptorMemoryManager.h" 00028 #include "PsnThreadMemoryManager.h" 00029 #include "PsnSystemMemoryManager.h" 00030 00031 #include <unistd.h> 00032 00033 PsnMultiThreadedBenchmarkingScheduler::PsnMultiThreadedBenchmarkingScheduler (unsigned int numberOfSteps, 00034 unsigned int numberOfThreads, 00035 bool createThreadAndLocalSchedulers, 00036 const int & sampleIndex, 00037 unsigned int numberOfSamples, 00038 ostream & outputFile ) : 00039 PsnScheduler(numberOfSteps), 00040 _numberOfThreads(numberOfThreads), 00041 _currentStep ( 0 ), 00042 _nextThreadForScheduling ( 0 ), 00043 _sampleIndex ( sampleIndex ), 00044 _numberOfSamples( numberOfSamples ), 00045 _outputFile ( outputFile ) 00046 00047 { 00048 assert ( _outputFile.good() ) ; 00049 00050 _barrier = new PsnBarrier ( _numberOfThreads + 1) ; 00051 00052 _threadIds = new pthread_t [ _numberOfThreads ] ; 00053 00054 _threadData = new vector <pair<PsnScheduler *, unsigned int> * > ( _numberOfThreads ) ; 00055 00056 for (int i = 0 ; i < _numberOfThreads ; i++ ) 00057 { 00058 (*_threadData)[i] = new pair<PsnScheduler *, unsigned int> (this, i) ; 00059 } 00060 00061 _localSchedulers = new vector <PsnScheduler *> ( _numberOfThreads ) ; 00062 00063 int ret; 00064 00065 #ifdef _SGI 00066 //for better use of the cpus available 00067 pthread_setconcurrency(_numberOfThreads) ; 00068 #endif 00069 00070 if ( createThreadAndLocalSchedulers ) 00071 { 00072 00073 _duplicatedObjectScheduler = new PsnBenchScheduler( numberOfSteps, 00074 _sampleIndex, 00075 _numberOfSamples, 00076 _outputFile ) ; 00077 00078 for (int i = 0 ; i < _numberOfThreads ; i++ ) 00079 { 00080 (*_localSchedulers)[i] = new PsnBenchScheduler( numberOfSteps, 00081 _sampleIndex, 00082 _numberOfSamples, 00083 _outputFile ) ; 00084 } 00085 00086 for (int i = 0 ; i < _numberOfThreads ; i++ ) 00087 { 00088 ret = pthread_create( & (_threadIds [i]), 00089 0, 00090 (void *(*)(void *))_threadContainer, 00091 (*_threadData)[i]); 00092 if (ret) 00093 { 00094 PsController::error("Thread creation impossible") ; 00095 } 00096 00097 } 00098 } 00099 00100 // create the data structures needed for benchmarking the waiting times 00101 _localWaitingTimes = new long * [ _numberOfThreads ] ; 00102 00103 for (int i = 0 ; i < _numberOfThreads ; i++ ) 00104 { 00105 _localWaitingTimes [ i ] = new long [ _numberOfSamples ] ; 00106 } 00107 00108 } 00109 00110 00111 PsnMultiThreadedBenchmarkingScheduler::~PsnMultiThreadedBenchmarkingScheduler() 00112 { 00113 //first, print the scheduling data. 00114 long totalTime = 0 ; 00115 00116 assert (_outputFile.good() ) ; 00117 00118 for (int i = 0 ; i < _numberOfThreads ; i++ ) 00119 { 00120 totalTime = 0 ; 00121 _outputFile <<"thread "<<i<<endl; 00122 for ( int j =0 ; j < _numberOfSamples ; j ++ ) 00123 { 00124 totalTime += _localWaitingTimes [i] [j] ; 00125 _outputFile <<_localWaitingTimes [i] [j] <<" , "; 00126 } 00127 _outputFile << "average " <<totalTime/_numberOfSamples<<endl; 00128 00129 delete _localWaitingTimes [ i ] ; 00130 00131 } 00132 00133 delete [] _localWaitingTimes ; 00134 00135 00136 // then take care of the multi-threading data 00137 for (int i = 0 ; i < _numberOfThreads ; i++ ) 00138 { 00139 // this will print the benchmarking data for each local scheduler 00140 delete (*_localSchedulers)[i] ; 00141 00142 delete (*_threadData)[i] ; 00143 00144 } 00145 00146 delete _localSchedulers ; 00147 00148 delete _barrier ; 00149 00150 delete [] _threadIds ; 00151 00152 delete _threadData ; 00153 00154 delete _duplicatedObjectScheduler ; 00155 } 00156 00157 00158 00159 void PsnMultiThreadedBenchmarkingScheduler::runStep (unsigned int which) 00160 { 00161 00162 _currentStep = which ; 00163 00164 _duplicatedObjectScheduler->runStep (which) ; 00165 00166 #if defined (_DEBUGSCHEDULER) 00167 cerr<<"PsnMultiThreadedScheduler::runStep : Execution by block for debug "<<endl; 00168 for ( int i = 0 ; i < _numberOfThreads ; i++ ) { 00169 cerr<<"Block "<<i<<" ***********************************"<<endl; 00170 (*_localSchedulers)[ i ]->runStep (which) ; 00171 } 00172 #else 00173 _barrier->Sync() ; 00174 00175 _barrier->Sync() ; 00176 //let the controller do it's work 00177 00178 //purge the memory manager from memory that couldn't be freed efficiently 00179 PsnThreadMemoryManager::freeLeakedMemoryBlocks() ; 00180 #endif 00181 } 00182 00183 00184 00185 void PsnMultiThreadedBenchmarkingScheduler::addToScheduable (PsnReferenceObjectHandle * ref, 00186 unsigned int when, 00187 unsigned int whichThread) 00188 { 00189 if (dynamic_cast<const PsDuplicatedObject *>(&((PsnReferenceObjectHandle *)ref)->getSimulatedObject())) 00190 { 00191 _duplicatedObjectScheduler->addToScheduable ( ref , when ) ; 00192 } 00193 else 00194 { 00195 (*_localSchedulers)[ whichThread ] -> addToScheduable( ref , when ) ; 00196 } 00197 } 00198 00199 00200 00201 void PsnMultiThreadedBenchmarkingScheduler::addToScheduable (PsnReferenceObjectHandle * ref, 00202 unsigned int when) 00203 { 00204 00205 if (dynamic_cast<const PsDuplicatedObject *>(&((PsnReferenceObjectHandle *)ref)->getSimulatedObject())) 00206 { 00207 _duplicatedObjectScheduler->addToScheduable ( ref , when ) ; 00208 } 00209 else 00210 { 00211 assert ( ref != NULL ) ; 00212 assert ( ref->getSimulatedObject().getFather () != NULL ); 00213 00214 //try and schedule an object on the same thread as it's father. 00215 map<PsnReferenceObjectHandle *, unsigned int>::iterator i = _whichThread.find((PsnReferenceObjectHandle *)ref->getSimulatedObject().getFather()->getObjectHandle() ) ; 00216 if ( i == _whichThread.end() ) 00217 { 00218 00219 (*_localSchedulers)[ _nextThreadForScheduling ] -> addToScheduable( ref , when ) ; 00220 #ifdef _DEBUGSCHEDULER 00221 cerr<<ref->getSimulatedObject().getObjectDescriptor().getName()<< " goes to thread "<<_nextThreadForScheduling<<endl; 00222 #endif 00223 _whichThread [ ref ] = _nextThreadForScheduling ; 00224 00225 _nextThreadForScheduling = ( _nextThreadForScheduling + 1 ) % _numberOfThreads ; 00226 00227 } 00228 else {//schedule on the same thread as ref's father 00229 00230 (*_localSchedulers)[ (*i).second ] -> addToScheduable( ref , when ) ; 00231 #ifdef _DEBUGSCHEDULER 00232 cerr<<ref->getSimulatedObject().getObjectDescriptor().getName()<< " goes to thread "<<(*i).second<<endl; 00233 #endif 00234 00235 _whichThread [ ref ] = (*i).second ; 00236 00237 } 00238 } 00239 } 00240 00241 00242 00243 void PsnMultiThreadedBenchmarkingScheduler::removeFromScheduable (PsnReferenceObjectHandle * ref) { 00244 00245 if (dynamic_cast<const PsDuplicatedObject *>(&((PsnReferenceObjectHandle *)ref)->getSimulatedObject())) 00246 { 00247 _duplicatedObjectScheduler->removeFromScheduable ( ref ) ; 00248 } 00249 else 00250 { 00251 (*_localSchedulers) [ _whichThread [ ref ] ] ->removeFromScheduable (ref ) ; 00252 } 00253 } 00254 00255 00256 00257 void PsnMultiThreadedBenchmarkingScheduler::schedule(PsnReferenceObjectHandle * ref) 00258 { 00259 if (dynamic_cast<const PsDuplicatedObject *>(&((PsnReferenceObjectHandle *)ref)->getSimulatedObject())) 00260 { 00261 _duplicatedObjectScheduler->schedule ( ref ) ; 00262 } 00263 else 00264 { 00265 (*_localSchedulers) [ _whichThread [ ref ] ] -> schedule (ref) ; 00266 } 00267 } 00268 00269 00270 00271 void PsnMultiThreadedBenchmarkingScheduler::unschedule(PsnReferenceObjectHandle * ref) 00272 { 00273 if (dynamic_cast<const PsDuplicatedObject *>(&((PsnReferenceObjectHandle *)ref)->getSimulatedObject())) 00274 { 00275 _duplicatedObjectScheduler->unschedule ( ref ) ; 00276 } 00277 else 00278 { 00279 (*_localSchedulers) [ _whichThread [ ref ] ] -> unschedule (ref) ; 00280 } 00281 } 00282 00283 00284 00285 void * PsnMultiThreadedBenchmarkingScheduler::_threadContainer (void * myThreadData) 00286 { 00287 // install the memory managers 00288 HeapStackTop systemMemoryManager ( HeapStackTop::getSystemMemoryManager() ) ; 00289 00290 PsnMemoryManager * currentMemoryManager = HeapStackTop::getSystemMemoryManager() ; 00291 00292 assert ( currentMemoryManager != 0 ) ; 00293 00294 size_t initialAllocatatedMemory = 1024 * 1024 ; 00295 00296 void * startMemory = currentMemoryManager->allocateSizeRemembered ( initialAllocatatedMemory ) ; 00297 00298 PsnDescriptorMemoryManager * descriptorMemoryManager = new PsnDescriptorMemoryManager ( *currentMemoryManager ) ; 00299 00300 descriptorMemoryManager->init() ; 00301 00302 PsnThreadMemoryManager * memoryManagerForThisThread ; 00303 00304 memoryManagerForThisThread = new PsnThreadMemoryManager ( startMemory, 00305 initialAllocatatedMemory, 00306 *currentMemoryManager, 00307 *descriptorMemoryManager ) ; 00308 memoryManagerForThisThread -> init() ; 00309 00310 HeapStackTop allocationContextForThisThread ( memoryManagerForThisThread ) ; 00311 00312 pair<PsnMultiThreadedBenchmarkingScheduler *, unsigned int> * threadData = ( pair<PsnMultiThreadedBenchmarkingScheduler *, unsigned int> * ) myThreadData ; 00313 00314 ( * threadData ).first->run( ( * threadData ).second ) ; 00315 00316 return threadData ; 00317 } 00318 00319 00320 void PsnMultiThreadedBenchmarkingScheduler::run( unsigned int whichFrameScheduler ) 00321 { 00322 #ifdef _SGI 00323 timespec dateBeforeSync, dateAfterSync ; 00324 int counter = 0 ; 00325 while ( true ) 00326 { 00327 00328 //wait for the controller to be ready 00329 _barrier->Sync() ; 00330 00331 (*_localSchedulers)[ whichFrameScheduler ]->runStep ( _currentStep ) ; 00332 00333 clock_gettime (CLOCK_SGI_CYCLE, &dateBeforeSync); 00334 00335 //wait for other local schdulers to be ready 00336 _barrier->Sync() ; 00337 00338 clock_gettime (CLOCK_SGI_CYCLE, &dateAfterSync); 00339 00340 if (dateAfterSync.tv_nsec >= dateBeforeSync.tv_nsec ) 00341 { 00342 _localWaitingTimes [whichFrameScheduler] [ counter ] = ( dateAfterSync.tv_nsec - dateBeforeSync.tv_nsec ) / 1000 ; 00343 } 00344 00345 counter = ( counter + 1 ) % _numberOfSamples ; 00346 } 00347 00348 #else 00349 timeval dateBeforeSync ; 00350 timeval dateAfterSync ; 00351 int counter = 0 ; 00352 while ( true ) 00353 { 00354 00355 //wait for the controller to be ready 00356 _barrier->Sync() ; 00357 00358 (*_localSchedulers)[ whichFrameScheduler ]->runStep ( _currentStep ) ; 00359 00360 gettimeofday(&dateBeforeSync, NULL); 00361 00362 //wait for other local schdulers to be ready 00363 _barrier->Sync() ; 00364 00365 gettimeofday(&dateAfterSync, NULL); 00366 00367 if (dateAfterSync.tv_usec >= dateBeforeSync.tv_usec ) 00368 { 00369 _localWaitingTimes [whichFrameScheduler] [ counter ] = dateAfterSync.tv_usec - dateBeforeSync.tv_usec ; 00370 } 00371 00372 counter = ( counter + 1 ) % _numberOfSamples ; 00373 } 00374 #endif 00375 }
| Documentation generated on Mon Nov 25 15:25:01 2002 |
Generated with doxygen 1.2.12 by Dimitri van Heesch , 1997-2001 |