OpenMP中的嵌套并行性

时间:2013-08-26 13:15:07

标签: nested openmp

我想将任务映射到三个线程,如下所示:

  1. taskAtaskBtaskC中的每一个都必须由不同的线程执行。

  2. taskA包含子任务task(1)task(2)task(3)

  3. taskB包含子任务task(11)task(12)task(13)

  4. taskC包含子任务task(21)task(22)task(23)

  5. 如果taskAtaskBtaskC中的任何一个完成且至少有一个未启动的另一个任务的子任务,则与完成的任务相关联的线程应该窃取未开始的子任务。

  6. 我无法实现此设置。我只能做以下MWE。在这个MWE中,线程不遵守规则2,3,4。

    这是我的MWE:

    double task(int taskid) {
        int tid = omp_get_thread_num();
        int nthreads = omp_get_num_threads();   
        printf("%d/%d: taskid=%d\n", tid, nthreads, taskid);
    
        int i;
        double t = 1.1;
        for(i = 0; i < 10000000*taskid; i++) {
            t *= t/i;
        }
        return t;
    }
    
    double taskA() {
        int tid = omp_get_thread_num();
        int nthreads = omp_get_num_threads();   
        printf("%s %d/%d\n", __FUNCTION__, tid, nthreads);
        double a, b, c;
        //#pragma omp parallel
        //#pragma omp single
        {
        #pragma omp task untied shared(a)
        a=task(1);
        #pragma omp task  untied shared(b)
        b=task(2);
        #pragma omp task  untied shared(c)
        c=task(3);
        }
        return a+b+c;
    }
    
    double taskB() {
        int tid = omp_get_thread_num();
        int nthreads = omp_get_num_threads();   
        printf("%s %d/%d\n", __FUNCTION__, tid, nthreads);  
        double a, b, c;
        //#pragma omp parallel
        //#pragma omp single
        {
        #pragma omp task  untied  shared(a)
        a=task(11);
        #pragma omp task  untied  shared(b)
        b=task(12);
        #pragma omp task  untied  shared(c)
        c=task(13);
        }
        return a+b+c;
    }
    
    double taskC() {
        int tid = omp_get_thread_num();
        int nthreads = omp_get_num_threads();   
        printf("%s %d/%d\n", __FUNCTION__, tid, nthreads);  
        double a, b, c;
        //#pragma omp parallel
        //#pragma omp single
        {
        #pragma omp task  untied  shared(a)
        a=task(21);
        #pragma omp task  untied  shared(b)
        b=task(22);
        #pragma omp task  untied  shared(c)
        c=task(23);
        }
        return a+b+c;
    }
    int main() {
        omp_set_num_threads(3);
        double a,b,c;
    
        #pragma omp parallel
        #pragma omp single
        {
            #pragma omp task untied
            a=taskA();
            #pragma omp task untied
            b=taskB();
            #pragma omp task untied
            c=taskC();
        }
        #pragma omp taskwait
        printf("%g %g %g\n", a, b, c);
        return 0;
    }
    

    编译为:

    icpc -Wall -fopenmp -O2 -o nestedomp nestedomp.c
    

    输出:

    taskC 1/3
    1/3: taskid=21
    taskA 2/3
    taskB 0/3
    0/3: taskid=23
    2/3: taskid=22
    1/3: taskid=1
    1/3: taskid=2
    2/3: taskid=3
    0/3: taskid=11
    1/3: taskid=12
    2/3: taskid=13
    

    这里,线程0开始处理任务23,但它必须开始处理1或11.

1 个答案:

答案 0 :(得分:0)

您可以使用线程ID来构建工作分配:

#pragma omp parallel num_threads(3)
{
 int tid = omp_get_thread_num();

 if (tid == 0) 
   //  Task 0
 } else if (tid == 1) {
   //  Task 1
 } else
   //  Task 2   
}

您可以根据需要设置线程数,并在任务级别引入嵌套。