Department of Scientific Computing   
Institute for Numerical Simulation   
University of Bonn   
Documentation
Download
Programming References
Bug Reports / Suggestions
FAQ
Authors
Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

SMP.hpp

00001 //
00002 // Functions required for SMP parallelization
00003 //
00004 
00005 #ifndef _SMP_HPP_
00006 #define _SMP_HPP_
00007 
00008 template<int DIM>
00009 void AdaptiveGrid<DIM>::SMPLoadBalance() {
00010     
00011   int     dir,i ;
00012   size_t  sall=Size(), n ;
00013   
00014   for (dir=0; dir<DIM; dir++) {
00015    
00016     // get vector of linear ordered AdaptiveLevels * w.r.t. direction dir
00017     ProjectionGrid              *pg=BasisPG[dir] ;
00018     ProjectionGrid::iterator     pgit ;
00019     AdaptiveLevelsPointer       *alpn ;
00020 
00021     size_t num_alp=0,s=0 ; // local number of AdaptiveLevels
00022     for (pgit=(*pg).begin(); pgit!=(*pg).end(); ++pgit) {
00023       // set AdaptiveLevelsPointer
00024       alpn    = &smpalptmp[num_alp] ;
00025       alpn->lt= (*pgit).first   ; // dimension reduced level/spatial index 
00026       alpn->a = (*pgit).second  ; // pointer
00027       alpn->s = alpn->a->size() ; // size
00028       s      += alpn->s         ;
00029       num_alp++ ;
00030       assert (num_alp < _MAX_ADAPTIVELEVELPOINTERS_) ;
00031 
00032     } // pgit
00033 
00034     if (s !=sall ) { std::cout<< "AdaptiveGrid<"<<DIM<<">::SMPLoadBalance dir="<<dir<<" s="<<s<<" sall="<<sall<<"\n"; exit(-1) ; }
00035    
00036     // load balancing:
00037     // first sort (decreasing order) w.r.t to alp->s all entries of Alptmp
00038     // the distribute all entries among the _SMP_PROC_ buckets such that
00039     // the current entry is put in the bucket with the lowest workcout (cummulative sizes)
00040     // because of the decreasing order of all entries this leads to a fairly good load balancing
00041 
00042     qsort((void *)smpalptmp, num_alp, sizeof(smpalptmp[0]), AdaptiveLevelsPointercmp) ;
00043 
00044     // indices of buckets for which the current workcount is minimal among all bckts.
00045     int mins[_SMP_PROC_], wrkc[_SMP_PROC_]={0}, curmin=_SMP_PROC_ -1 ;
00046     
00047     for (i=0; i< _SMP_PROC_; i++) {
00048       mins           [i] = i ; // all wrkc[i]==0 -> all are minimal buckets
00049       smpnum_alp[dir][i] = 0 ; // counter for AdaptiveLevels to be processed by SMPjob  
00050     }
00051 
00052     // just count number of AdaptiveLevels to be processed by thread i, do not distribute
00053     for (n=0; n<num_alp; n++) {
00054       // minimal bucket
00055       size_t bckt=mins[curmin] ;
00056 
00057       smpnum_alp[dir][bckt] += 1 ;
00058       wrkc           [bckt] += smpalptmp[n].s ;
00059       
00060       // find new minimal buckets
00061       curmin-- ;
00062       if (curmin<0) {
00063         int mi=MAXINT ;
00064         for (i=0; i < _SMP_PROC_; i++)
00065           mi = (wrkc[i]<mi) ? wrkc[i] : mi ;
00066 
00067         curmin=-1 ;
00068         for (i=0; i < _SMP_PROC_; i++)
00069           if (wrkc[i]==mi) mins[++curmin] = i ;
00070       }
00071     }
00072 
00073     // now compute those parts where the AdaptiveLevels are stored which should be 
00074     // processed by Thread i: from smpJobs[dir][i] to smpJobs[dir][i]-1
00075 
00076     size_t off[_SMP_PROC_+1]={0} ;
00077     for (i=0; i< _SMP_PROC_; i++) {
00078       smpalpstart[dir][i] = &smpalp[dir][off[i]] ;
00079       off[i+1]            = off[i] + smpnum_alp[dir][i] ;
00080     }
00081     
00082     // now distribute
00083 
00084     size_t nalp[_SMP_PROC_]={0} ; // mirror of SMPjobs[dir][ .. ].nalp 
00085     for (i=0; i < _SMP_PROC_; i++) {
00086       mins[i]=i ;
00087       wrkc[i]=0 ;
00088       nalp[i]=0 ;
00089     }
00090     curmin=_SMP_PROC_-1;
00091 
00092     for (n=0; n<num_alp; n++) {
00093       size_t bckt=mins[curmin] ;
00094       // insert in bucket in
00095       smpalp[dir][off[bckt] + nalp[bckt]].Copy( &smpalptmp[n] ) ;
00096       nalp  [bckt] += 1 ;
00097       wrkc  [bckt] += smpalptmp[n].s ;
00098       
00099       // find new minimal buckets
00100       curmin-- ;
00101       if (curmin<0) {
00102         int mi=MAXINT ;
00103         for (i=0; i < _SMP_PROC_; i++)
00104           mi = (wrkc[i]<mi) ? wrkc[i] : mi ;
00105 
00106         curmin=-1 ;
00107         for (i=0; i < _SMP_PROC_; i++)
00108           if (wrkc[i]==mi) mins[++curmin] = i ;
00109       }
00110     }
00111 
00112   } // next dir
00113 }
00114 
00115 
00116 //
00117 // wait for SMP jobs to be finished
00118 // 
00119 template <int DIM>
00120 void AdaptiveGrid<DIM>::SMPWaitForAllThreads() {
00121   size_t i,cnt=0 ;
00122   bool   finishedall, finished[_SMP_PROC_] ;
00123 
00124   do {
00125     finishedall=true ;
00126     for (i=1; i< _SMP_PROC_; i++)  finishedall &= (finished[i] = SMPjobs[i].isfinished()) ;
00127   
00128     // determine whether the pending threads catched the signal at least
00129     if ( (!finishedall) && ((cnt%1000000)==0) ) {
00130       for (i=1; i< _SMP_PROC_; i++) 
00131         if ( (!finished[i]) && (smpjobcount != SMPjobs[i].jobcount) ) 
00132           if (debugRefine) std::cout<<"SMPjob "<<i<<" ("<<&SMPjobs[i]<<") did not catched the signal "<<smpjobcount<<" "<< SMPjobs[i].jobcount<<"\n" ;
00133     }
00134      
00135     cnt++ ;
00136   } while (! finishedall ) ;
00137 }
00138 
00139 #endif
00140 

Generated at Mon Aug 19 10:02:32 2002 for AWFD by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001