tags:

views:

92

answers:

3

Hi StackOverflow,

I have an application that is parallellized using pthreads. The application has a iterative routine call and a thread spawn within the rountine (pthread_create and pthread_join) to parallelize the computation intensive section in the routine. When I use an instrumenting tool like PIN to collect the statistics the tool reports statistics for several threads(no of threads x no of iterations). I beleive it is because it is spawning new set of threads each time the routine is called.

  1. How can I ensure that I create the thread only once and all successive calls use the threads that have been created first.

  2. When I do the same with OpenMP and then try to collect the statistics, I see that the threads are created only once. Is it beacause of the OpenMP runtime ?

EDIT:

im jus giving a simplified version of the code.

int main() 
{ 
  //some code 
  do { 
    compute_distance(objects,clusters, &delta); //routine with pthread 
  } while (delta > threshold ) 
}
void compute_distance(double **objects,double *clusters, double *delta) 
{ 
   //some code again 
   //computation moved to a separate parallel routine.. 
   for (i=0, i<nthreads;i++) 
     pthread_create(&thread[i],&attr,parallel_compute_phase,(void*)&ip); 
   for (i=0, i<nthreads;i++) 
     rc = pthread_join(thread[i], &status); 
} 

I hope this clearly explains the problem.

  1. How do we save the thread id and test if was already created?
A: 

You can make a simple thread pool implementation which creates threads and makes them sleep. Once a thread is required, instead of "pthread_create", you can ask the thread pool subsystem to pick up a thread and do the required work.. This will ensure your control over the number of threads..

Salil
Hi.. Thanks for the response. The issue is that im using benchmarks from a benchmark suite and I do not want to make lot of changes to the original source code. This is the correct way to do it but I wanted to know if there is a work around to avoid making lots of changes to the source code.
madman
A: 

An easy thing you can do with minimal code changes is to write some wrappers for pthread_create and _join. Basically you can do something like:

typedef struct {
  volatile int go;
  volatile int done;
  pthread_t h;
  void* (*fn)(void*);
  void* args;
} pthread_w_t;

void* pthread_w_fn(void* args) {
    pthread_w_t* p = (pthread_w_t*)args;
    // just let the thread be killed at the end
    for(;;) {
        while (!p->go) { pthread_yield(); };  // yields are good
        p->go = 0;  // don't want to go again until told to
        p->fn(p->args);
        p->done = 1;
    }
}

int pthread_create_w(pthread_w_t* th, pthread_attr_t* a,
                     void* (*fn)(void*), void* args) {
    if (!th->h) {
        th->done = 0;
        th->go = 0;
        th->fn = fn;
        th->args = args;
        pthread_create(&th->h,a,pthread_w_fn,th);
    }
    th->done = 0; //make sure join won't return too soon
    th->go = 1;   //and let the wrapper function start the real thread code
}

int pthread_join_w(pthread_w_t*th) {
  while (!th->done) { pthread_yield(); };
}

and then you'll have to change your calls and pthread_ts, or create some #define macros to change pthread_create to pthread_create_w etc....and you'll have to init your pthread_w_ts to zero.

Messing with those volatiles can be troublesome though. you'll probably need to spend some time getting my rough outline to actually work properly.

quarter
A: 

To ensure something that several threads might try to do only happens once, use pthread_once(). To ensure something only happens once that might be done by a single thread, just use a bool (likely one in static storage).

Honestly, it would be far easier to answer your question for everyone if you would edit your question – not comment, since that destroys formatting – to contain the real code in question, including the OpenMP pragmas.

Jeremy W. Sherman