如何正确屈服/恢复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 masternn", 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处理,而其他线程是空闲的。

是否必须以不同的方式发布或屈服这些任务,还是Intel的OpenMP运行时(尚未)可以处理此任务?顺便说一句,GNU GCC 4.9.2根本不屈服。

我认为您的代码很好,这是一个实现问题。实际上,在LLVM OpenMP实施中,这与英特尔的实施非常相关 - 两周前推动了一项提交,从而解决了您的问题。在我的测试中,Clang的当前libiomp5.so(由中继构建)仅通过设置LD_LIBRARY_PATH并产生所需的结果与icc 17.0.4兼容。

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根本没有屈服,但没有详细研究。

我不知道是否以及何时将更改合并到Intel运输的库中。

更新:您是正确的,行为仍然不是最佳的。从简要浏览代码,libiomp似乎支持绑定的任务的概念,而是在taskwait期间不需要该任务,而只是执行另一个任务并保留堆栈中暂停任务的上下文。我怀疑适当的支持将需要更多的重型编译器支持(一种连续),而不仅仅是生成库电话。

再次,您正在做正确的事情,但是编译器/运行时还不够复杂,无法支持标准允许(该行为完全符合标准标准)。另请注意,对于libiomp的当前行为,甚至不需要任何任务,因为它们只是到目前为止的排队。似乎没有一种简单的方法来获得所需的东西,而没有分解/链式任务。

最新更新