Neo1989
Neo1989

Reputation: 295

OpenMP: recursively subdividing work and threads

I wonder how below logic can be written using OpenMP:

do_something(Job job, Threads x ... x+b){
    if(b<1)  // if only one thread is assigned
        do_real_work(job); return;

    // otherwise, divide the work in two subtasks
    // Only one thread executes this:
    Divide job into job1 and job2

    // Divide the assigned threads into two groups
    // and assign the subtasks to them.
    // The below two lines should be executed in parallel.
    do_something(job1, x ... x+b/2)
    do_something(job2, x+b/2 ... x+b)
}

The above workflow by itself is simply divide-and-conquer. I want to divide the work among n threads in a "binary-tree" style. Particularly, I want the program to be able to obtain the # of threads from, say, evn var, and take care of the division recursively. If 4 threads are used, then two levels are executed; If 8 threads are used, then three levels are executed, etc.

I have no idea how one can designate a subset of threads to execute a parallel task in OpenMP. And is it even possible to specify the thread IDs to carry out the task?

Upvotes: 0

Views: 1157

Answers (1)

Hristo Iliev
Hristo Iliev

Reputation: 74475

Although it is possible to obtain the thread ID using omp_get_thread_num() and branch according to this ID, it seems that your problem is more appropriate for being solved using explicit tasks. The maximum number of OpenMP threads as set in the environment variable OMP_NUM_THREADS could be obtained by calling omp_get_max_threads() (even outside a parallel region) and the actual number could be obtained by calling omp_get_num_threads() inside an active region. The parallel code should look something like:

do_something(Job job, Threads x ... x+b){
    if(b<1)  // if only one thread is assigned
        do_real_work(job); return;

    // otherwise, divide the work in two subtasks
    // Only one thread executes this:
    Divide job into job1 and job2

    // Divide the assigned threads into two groups
    // and assign the subtasks to them.
    // The below two lines should be executed in parallel.
    #pragma omp task
    do_something(job1, x ... x+b/2)

    #pragma omp task
    do_something(job2, x+b/2 ... x+b)
}

// Call like follows

#pragma omp parallel
{
   #pragma omp single
   {
      b = omp_get_num_threads();
      do_something(job, x, b);
   }
}

Upvotes: 1

Related Questions