Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

PsnMultiThreadedBenchmarkingScheduler.cxx

Go to the documentation of this file.
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 }

logo OpenMask

Documentation generated on Mon Nov 25 15:25:01 2002

Generated with doxygen 1.2.12 by Dimitri van Heesch ,   1997-2001