我编写了一个小型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根本不会产生任务。
答案 0 :(得分:0)
我认为你的代码很好,这是一个实现问题。事实上,在LLVM OpenMP实施中 - 这与英特尔 - pushed a commit two weeks ago非常相关,可以解决您的问题。在我的测试中,clang的当前libiomp5.so
(由主干构建)仅通过设置icc 17.0.4
与LD_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
所描述的当前行为,任务甚至不需要解开,因为它们目前只是队列。似乎并不是一种简单的方法来获得你想要的东西,而不是拆分/链接任务。