如何正确地生成/恢复OpenMP解决的任务?

时间:2017-12-05 16:44:23

标签: task openmp

我编写了一个小型C程序来评估OpenMP在任务空闲时间发生时(或等待通信数据)产生另一项任务的能力:

#include <stdio.h>
#include <sys/time.h>
#include <omp.h>

#define NTASKS 10

double wallClockTime(void) {

    struct timeval t;

    gettimeofday(&t, NULL);

    return (double)(t.tv_sec + t.tv_usec/1000000.);
}

void printStatus(char *status, int taskNum, int threadNum) {

#pragma omp critical(printStatus)
    {
        int i;
        for (i = 0; i < taskNum; i++) printf("    ");
        printf(" %s%i \n", status, threadNum);
    }
}

void task(int taskNum) {

    // "r"un task
    printStatus("r", taskNum, omp_get_thread_num());
    sleep(1);

    // "s"leeping task that can yield
    printStatus("s", taskNum, omp_get_thread_num());
    double idleStartTime = wallClockTime();
    while (wallClockTime() < idleStartTime + 1) {
#pragma omp taskyield
    }

    // "c"ontinue task
    printStatus("c", taskNum, omp_get_thread_num());
    sleep(1);
}


int main(int argc, char* argv[]) {

#pragma omp parallel
#pragma omp single nowait
    {
        int i;

        printf("thread %d is master\n\n", omp_get_thread_num());
        for (i = 0; i < NTASKS; i++) printf(" %02d ", i);
        printf("\n");

        for (i = 0; i < NTASKS; i++) {

#pragma omp task untied
            task(i);
        }
    }

    return 0;
}

我使用的是Intel C编译器17.0.4。以下是具有3个线程的运行的输出:

thread 0 is master

 00  01  02  03  04  05  06  07  08  09 
 r1 
                                     r0 
     r2 
 s1 
                                     s0 
     s2 
                                 r0 
 c1 
     c2 
                                 s0 
                             r0 
         r1 
             r2 
                             s0 
                         r0 
         s1 
             s2 
                         s0 
                     r0 
         c1 
             c2 
                     s0 
                 r0 
                 s0 
                 c0 
                     c0 
                         c0 
                             c0 
                                 c0 
                                     c0

线程1和2根本没有产生,但它们坚持使用它们分配的任务。我还希望线程1和2继续执行暂停的解决任务04 ... 09,但这些只由主线程0处理,而其他线程处于空闲状态。

是否必须以不同的方式发布或产生任务,或者英特尔的OpenMP运行时是否还能够处理这个问题?顺便说一下,GNU gcc 4.9.2根本不会产生任务。

1 个答案:

答案 0 :(得分:0)

我认为你的代码很好,这是一个实现问题。事实上,在LLVM OpenMP实施中 - 这与英特尔 - pushed a commit two weeks ago非常相关,可以解决您的问题。在我的测试中,clang的当前libiomp5.so(由主干构建)仅通过设置icc 17.0.4LD_LIBRARY_PATH兼容并产生所需的结果。

thread 0 is master

 00  01  02  03  04  05  06  07  08  09 
                                     r0 
 r2 
     r1 
                                     s0 
                                 r0 
 s2 
         r2 
     s1 
             r1 
                                 s0 
                             r0 
         s2 
                 r2 
             s1 
                     r1 
                             s0 
                         r0 
                 s2 
                     s1 
                 c2 
                         s0 
                     c1 
                         c0 
         c2 
             c1 
                             c0 
 c2 
     c1 
                                 c0 
                                     c0 

我也可以确认gcc根本没有收益,但是没有仔细查看。

我不知道是否以及何时将更改合并到英特尔发布的库中。

更新:你是对的,行为仍然不是最佳的。通过简要查看代码,似乎libiomp支持绑定任务的概念,但不会在taskwait期间重新排队任务,而只是执行另一个任务并保留挂起任务的上下文。堆。我怀疑适当的支持需要更多繁重的编译器支持(继续排序),而不仅仅是生成库调用。

同样,您正在做的一切正确,但编译器/运行时不够复杂,无法支持标准允许(行为完全符合标准)。另请注意,对于libiomp所描述的当前行为,任务甚至不需要解开,因为它们目前只是队列。似乎并不是一种简单的方法来获得你想要的东西,而不是拆分/链接任务。