BandSPDLinThreadSolver.cpp

Go to the documentation of this file.
00001 /* ****************************************************************** **
00002 **    OpenSees - Open System for Earthquake Engineering Simulation    **
00003 **          Pacific Earthquake Engineering Research Center            **
00004 **                                                                    **
00005 **                                                                    **
00006 ** (C) Copyright 1999, The Regents of the University of California    **
00007 ** All Rights Reserved.                                               **
00008 **                                                                    **
00009 ** Commercial use of this program without express permission of the   **
00010 ** University of California, Berkeley, is strictly prohibited.  See   **
00011 ** file 'COPYRIGHT'  in main directory for information on usage and   **
00012 ** redistribution,  and for a DISCLAIMER OF ALL WARRANTIES.           **
00013 **                                                                    **
00014 ** Developed by:                                                      **
00015 **   Frank McKenna (fmckenna@ce.berkeley.edu)                         **
00016 **   Gregory L. Fenves (fenves@ce.berkeley.edu)                       **
00017 **   Filip C. Filippou (filippou@ce.berkeley.edu)                     **
00018 **                                                                    **
00019 ** ****************************************************************** */
00020                                                                         
00021 // $Revision: 1.2 $
00022 // $Date: 2003/02/14 23:02:01 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/system_of_eqn/linearSOE/bandSPD/BandSPDLinThreadSolver.cpp,v $
00024                                                                         
00025                                                                         
00026 // File: ~/system_of_eqn/linearSOE/bandSPD/BandSPDLinThreadSolver.h
00027 //
00028 // Written: fmk 
00029 // Created: Mar, 1998
00030 // Revision: A
00031 //
00032 // Description: This file contains the class definition for 
00033 // BandSPDLinThreadSolver. It solves the BandSPDLinSOE object by calling
00034 // Thread routines.
00035 //
00036 // What: "@(#) BandSPDLinThreadSolver.h, revA"
00037 
00038 #include <BandSPDLinThreadSolver.h>
00039 #include <BandSPDLinSOE.h>
00040 #include <f2c.h>
00041 #include <math.h>
00042 #include <thread.h>
00043 
00044 // global data that will be needed by the threads
00045 struct thread_control_block {
00046   mutex_t start_mutex;
00047   mutex_t end_mutex;
00048   mutex_t startBlock_mutex;
00049   mutex_t endBlock_mutex;
00050 
00051   cond_t start_cond;
00052   cond_t end_cond;
00053   cond_t startBlock_cond;
00054   cond_t endBlock_cond;
00055 
00056   double *A,*X,*B;
00057   int n, kd;
00058   int blockSize, currentBlock;
00059   int workToDo;
00060   int info;
00061   int threadID;
00062   int numThreads;
00063   int threadsDone;
00064   int threadsDoneBlock;
00065 } TCB_BandSPDLinThreadSolver;
00066 
00067 
00068 BandSPDLinThreadSolver::BandSPDLinThreadSolver()
00069 :BandSPDLinSolver(SOLVER_TAGS_BandSPDLinThreadSolver), NP(1), 
00070  running(false), blockSize(1)
00071 {
00072   
00073 }
00074 
00075 BandSPDLinThreadSolver::BandSPDLinThreadSolver(int numProcessors, int blckSize)
00076 :BandSPDLinSolver(SOLVER_TAGS_BandSPDLinThreadSolver), NP(numProcessors),
00077  running(false), blockSize(blckSize)
00078 {
00079 
00080 }
00081 
00082 BandSPDLinThreadSolver::~BandSPDLinThreadSolver()
00083 {
00084     
00085 }
00086 
00087 
00088 extern "C" int dpbsv_(char *UPLO, int *N, int *KD, int *NRHS, 
00089                       double *A, int *LDA, double *B, int *LDB, 
00090                       int *INFO);
00091 
00092 extern "C" int dpbtrf_(char *UPLO, int *N, int *KD, double *A, 
00093                        int *LDA, int *INFO);
00094 
00095 extern "C" int dpbtrs_(char *UPLO, int *N, int *KD, int *NRHS, 
00096                        double *A, int *LDA, double *B, int *LDB, 
00097                        int *INFO);
00098                        
00099 
00100 void *BandSPDLinThreadSolver_Worker(void *arg);
00101 
00102 
00103 int
00104 BandSPDLinThreadSolver::solve(void)
00105 {
00106     if (theSOE == 0) {
00107         opserr << "BandSPDLinThreadSolver::solve(void)- ";
00108         opserr << " No LinearSOE object has been set\n";
00109         return -1;
00110     }
00111 
00112     int n = theSOE->size;
00113     int kd = theSOE->half_band -1;
00114     int ldA = kd +1;
00115     int nrhs = 1;
00116     int ldB = n;
00117     int info;
00118     double *Aptr = theSOE->A;
00119     double *Xptr = theSOE->X;
00120     double *Bptr = theSOE->B;
00121 
00122     // first copy B into X
00123     for (int i=0; i<n; i++)
00124         *(Xptr++) = *(Bptr++);
00125     Xptr = theSOE->X;
00126 
00127     // now solve AX = Y
00128     if (theSOE->factored == false) {
00129 
00130       // start threads running
00131       if (running == false) {
00132         mutex_init(&TCB_BandSPDLinThreadSolver.start_mutex, USYNC_THREAD, 0);
00133         mutex_init(&TCB_BandSPDLinThreadSolver.end_mutex, USYNC_THREAD, 0);
00134         mutex_init(&TCB_BandSPDLinThreadSolver.startBlock_mutex, USYNC_THREAD, 0);
00135         mutex_init(&TCB_BandSPDLinThreadSolver.endBlock_mutex, USYNC_THREAD, 0);
00136         cond_init(&TCB_BandSPDLinThreadSolver.start_cond, USYNC_THREAD, 0);
00137         cond_init(&TCB_BandSPDLinThreadSolver.end_cond, USYNC_THREAD, 0);
00138         cond_init(&TCB_BandSPDLinThreadSolver.startBlock_cond, USYNC_THREAD, 0);
00139         cond_init(&TCB_BandSPDLinThreadSolver.endBlock_cond, USYNC_THREAD, 0);
00140         TCB_BandSPDLinThreadSolver.workToDo = 0;
00141         
00142         // Create the threads - Bound daemon threads
00143         for (int j = 0; j < NP; j++) 
00144           thr_create(NULL,0, BandSPDLinThreadSolver_Worker, NULL, 
00145                      THR_BOUND|THR_DAEMON, NULL);
00146 
00147         running = true;
00148       }
00149       
00150   
00151       mutex_lock(&TCB_BandSPDLinThreadSolver.start_mutex); 
00152         // assign the global variables the threads will need
00153         TCB_BandSPDLinThreadSolver.A = Aptr;
00154         TCB_BandSPDLinThreadSolver.X = Xptr;
00155         TCB_BandSPDLinThreadSolver.B = Bptr;
00156         TCB_BandSPDLinThreadSolver.n = n;
00157         TCB_BandSPDLinThreadSolver.kd = kd;
00158         TCB_BandSPDLinThreadSolver.info = 0;
00159         TCB_BandSPDLinThreadSolver.workToDo = NP;
00160         TCB_BandSPDLinThreadSolver.blockSize = blockSize;
00161         TCB_BandSPDLinThreadSolver.currentBlock = -1;
00162         TCB_BandSPDLinThreadSolver.threadID = 0;
00163         TCB_BandSPDLinThreadSolver.numThreads = NP;
00164         TCB_BandSPDLinThreadSolver.threadsDone = 0;
00165         TCB_BandSPDLinThreadSolver.threadsDoneBlock = NP;
00166 
00167         // wake up the threads
00168         cond_broadcast(&TCB_BandSPDLinThreadSolver.start_cond);
00169       mutex_unlock(&TCB_BandSPDLinThreadSolver.start_mutex); 
00170 
00171       // yield the LWP
00172       thr_yield();
00173  
00174       // wait for all the threads to finish
00175       mutex_lock(&TCB_BandSPDLinThreadSolver.end_mutex);
00176 
00177          while (TCB_BandSPDLinThreadSolver.threadsDone < NP) 
00178            cond_wait(&TCB_BandSPDLinThreadSolver.end_cond, &TCB_BandSPDLinThreadSolver.end_mutex);
00179 
00180       mutex_unlock(&TCB_BandSPDLinThreadSolver.end_mutex);
00181     }
00182 
00183     // solve using factored matrix
00184     dpbtrs_("U",&n,&kd,&nrhs,Aptr,&ldA,Xptr,&ldB,&info);
00185     
00186 
00187     // check if successfull
00188     if (info != 0)
00189         return info;
00190 
00191     theSOE->factored = true;
00192     return 0;
00193 }
00194     
00195 
00196 
00197 int
00198 BandSPDLinThreadSolver::setSize()
00199 {
00200     // nothing to do    
00201     return 0;
00202 }
00203 
00204 
00205 int
00206 BandSPDLinThreadSolver::sendSelf(Channel &theChannel, 
00207                                  FEM_ObjectBroker &theBroker)
00208 {
00209     // nothing to do
00210     return 0;
00211 }
00212 
00213 int
00214 BandSPDLinThreadSolver::recvSelf(Channel &theChannel, 
00215                                  FEM_ObjectBroker &theBroker)
00216 {
00217     // nothing to do
00218     return 0;
00219 }
00220 
00221 
00222 
00223 
00224 // Thread routine called from thr_create() as a Bound Daemon Thread
00225 void *BandSPDLinThreadSolver_Worker(void *arg)
00226 {
00227   // Do this loop forever - or until all the Non-Daemon threads have exited
00228   while(true)
00229     {
00230 
00231       // Wait for some work to do
00232       mutex_lock(&TCB_BandSPDLinThreadSolver.start_mutex);
00233 
00234         while (TCB_BandSPDLinThreadSolver.workToDo == 0)
00235           cond_wait(&TCB_BandSPDLinThreadSolver.start_cond, &TCB_BandSPDLinThreadSolver.start_mutex);
00236 
00237         TCB_BandSPDLinThreadSolver.workToDo--;
00238 
00239         // get an id;
00240         int myID = TCB_BandSPDLinThreadSolver.threadID++;
00241 
00242       mutex_unlock(&TCB_BandSPDLinThreadSolver.start_mutex);
00243 
00244       // do some initialisation for the factorization
00245       int currentBlock =0;
00246       int n = TCB_BandSPDLinThreadSolver.n;
00247       int kd = TCB_BandSPDLinThreadSolver.kd;
00248       int blckSize = TCB_BandSPDLinThreadSolver.blockSize;
00249       double *Aptr = TCB_BandSPDLinThreadSolver.A;
00250       double *Bptr = TCB_BandSPDLinThreadSolver.B;
00251       double *Xptr = TCB_BandSPDLinThreadSolver.X;
00252       int numThreads = TCB_BandSPDLinThreadSolver.numThreads;
00253     
00254       int nBlocks = n/blckSize;
00255 
00256       for (int i=0; i<nBlocks; i++) {
00257         int currentDiagThread = i%numThreads;
00258         if (myID == currentDiagThread) {
00259 
00260           // wait till last block row is done
00261           mutex_lock(&TCB_BandSPDLinThreadSolver.endBlock_mutex);
00262             while(TCB_BandSPDLinThreadSolver.threadsDoneBlock < numThreads)
00263               cond_wait(&TCB_BandSPDLinThreadSolver.endBlock_cond, &TCB_BandSPDLinThreadSolver.endBlock_mutex);
00264 
00265             TCB_BandSPDLinThreadSolver.threadsDoneBlock = 0;
00266           mutex_unlock(&TCB_BandSPDLinThreadSolver.endBlock_mutex);        
00267 
00268           // FACTOR DIAG BLOCK
00269        
00270           // allow other threads to now proceed
00271           mutex_lock(&TCB_BandSPDLinThreadSolver.startBlock_mutex);
00272             TCB_BandSPDLinThreadSolver.currentBlock = i;
00273 
00274             cond_broadcast(&TCB_BandSPDLinThreadSolver.startBlock_cond);
00275           mutex_unlock(&TCB_BandSPDLinThreadSolver.startBlock_mutex);        
00276 
00277           
00278           // FACTOR REST OF BLOCK ROW BELONGING TO THREAD
00279 
00280           // mark that the thread has finished with row
00281           mutex_lock(&TCB_BandSPDLinThreadSolver.endBlock_mutex);
00282             TCB_BandSPDLinThreadSolver.threadsDoneBlock++;
00283 
00284             cond_signal(&TCB_BandSPDLinThreadSolver.endBlock_cond);
00285           mutex_unlock(&TCB_BandSPDLinThreadSolver.endBlock_mutex);                   
00286         }
00287         else {
00288 
00289           // wait till diag i is done 
00290           mutex_lock(&TCB_BandSPDLinThreadSolver.startBlock_mutex);
00291              while (TCB_BandSPDLinThreadSolver.currentBlock < i)
00292                 cond_wait(&TCB_BandSPDLinThreadSolver.startBlock_cond, 
00293                           &TCB_BandSPDLinThreadSolver.startBlock_mutex); 
00294           mutex_unlock(&TCB_BandSPDLinThreadSolver.startBlock_mutex);
00295 
00296           // FACTOR REST OF BLOCK ROW BELONGING TO THREAD
00297 
00298           // mark that the thread has finished with row
00299           mutex_lock(&TCB_BandSPDLinThreadSolver.endBlock_mutex);
00300             TCB_BandSPDLinThreadSolver.threadsDoneBlock++;
00301 
00302             cond_signal(&TCB_BandSPDLinThreadSolver.endBlock_cond);
00303           mutex_unlock(&TCB_BandSPDLinThreadSolver.endBlock_mutex);                             
00304         }
00305       }
00306 
00307       // signal the main thread that this thread is done with the work
00308       mutex_lock(&TCB_BandSPDLinThreadSolver.end_mutex);
00309          TCB_BandSPDLinThreadSolver.threadsDone++;
00310 
00311          cond_signal(&TCB_BandSPDLinThreadSolver.end_cond);
00312       mutex_unlock(&TCB_BandSPDLinThreadSolver.end_mutex);
00313     } 
00314   return NULL;
00315 }
00316 
00317 
00318 
00319 
00320 
00321 
00322 

Generated on Mon Oct 23 15:05:28 2006 for OpenSees by doxygen 1.5.0