c-函数依赖关系openMP



我有5个函数A、B、C、D、E。

为了执行D,为了执行E,我需要执行A、D。

我试过这个

int main()
{
#pragma omp parallel num_threads(5) 
{
long t1 = clock();
int a = 0, b = 0, c = 0, d = 0, e = 0;
int th = omp_get_thread_num();
if (th == 0) {
a += A();
printf("A is finished after %dn", clock() - t1);
}
if (th == 1) {
b += B();
printf("B is finished after %dn", clock() - t1);
}
if (th == 2) {
c += C();
printf("C is finished after %dn", clock() - t1);
}
if (th == 3 && (b == 1 && c == 1)) {
d += D();
printf("D is finished after %dn", clock() - t1);
}
if (th == 4 && (a == 1 && d == 1)) {
e += E();
printf("E is finished after %dn", clock() - t1);
}
}
return 0;
}

但D、E尚未执行

到目前为止,所有这些函数都返回1,用于调试

一个合适的OpenMP解决方案是使用具有数据依赖性的任务:

#pragma omp parallel num_threads(3)
#pragma omp single
{
double t1 = omp_wtime();
int a = 0, b = 0, c = 0, d = 0, e = 0;
#pragma omp task shared(a) depend(out: a)
{
a += A();
printf("A is finished after %fn", omp_wtime() - t1);
}
#pragma omp task shared(b) depend(out: b)
{
b += B();
printf("B is finished after %fn", omp_wtime() - t1);
}
#pragma omp task shared(c) depend(out: c)
{
c += C();
printf("C is finished after %fn", omp_wtime() - t1);
}
#pragma omp task shared(b,c,d) depend(in: b,c) depend(out: d)
{
d += D();
printf("D is finished after %fn", omp_wtime() - t1);
}
#pragma omp task shared(a,d,e) depend(in: a,d)
{
e += E();
printf("E is finished after %fn", omp_wtime() - t1);
}
}

这里,任务A被标记为具有depend(out: a)a的值的生产者,并且任务D被标记为带有depend(out: d)d的生产者。任务Edepend(in: a,d)标记为这两个值的使用者。根据输出(生产者(和输入(消费者(依赖关系,OpenMP运行时构建一个执行DAG(有向无环图(,"告诉"它所有任务的正确执行顺序。你也不需要五个线程——三个就足够了。

single构造中包含任务代码是非常惯用的OpenMP。

OpenMP 4.0早在2013年就引入了任务依赖性,因此除了MSVC++之外的任何现代编译器都应该支持该功能。

变量abcd,不能用于在线程之间通信,因为它们都是私有。因此,每个线程都有自己的私有副本。此外,将它们用于同步目的通常不是一个好主意。

在您的代码中,thread=3永远不会在if (th == 3 && (b == 1 && c == 1))上等待,因为:

  1. bc是私有的,因此无论其他线程对变量b=0c=0副本做了什么,thread=3都有b=0c=0
  2. 没有 告诉线程等待(例如,一些类似同步的构造函数(

如果希望线程相互等待,请改用omp barrier。所有线程都必须调用屏障,然后才能继续进行计算。

int main()
{
#pragma omp parallel num_threads(5) 
{
long t1 = clock();
int a = 0, b = 0, c = 0, d = 0, e = 0;
int th = omp_get_thread_num();
if (th == 0) {
a += A();
printf("A is finished after %dn", clock() - t1);
}
if (th == 1) {
b += B();
printf("B is finished after %dn", clock() - t1);
}
if (th == 2) {
c += C();
printf("C is finished after %dn", clock() - t1);
}
// Threads will wait for each other here
#pragma omp barrier 
if (th == 3) {
d += D();
printf("D is finished after %dn", clock() - t1);
}
// Threads will wait for each other here
#pragma omp barrier 
if (th == 4) {
e += E();
printf("E is finished after %dn", clock() - t1);
}
}
return 0;
}

一种更复杂的方法是使用具有依赖性的任务,这是在OpenMP 4.0标准上发布的一项功能。关于这个功能如何在这个线程上工作,已经有了很好的解释。

int a = 0, b = 0, c = 0, d = 0, e = 0;
#pragma omp parallel num_threads(5) shared(a, b, c, d)
{
#pragma omp single nowait
{
long t1 = clock();
int th = omp_get_thread_num();
#pragma omp task  depend (out:a) 
{
a += A();
printf("A is finished after %dn", clock() - t1);
}
#pragma omp task depend (out:b) 
{
b += B();
printf("B is finished after %dn", clock() - t1);
}
#pragma omp task depend (out:c) 
{ 
c += C();
printf("C is finished after %dn", clock() - t1);
}
#pragma omp task depend (in:a, b) depend(out:d) 
{
d += D(); 
printf("D is finished after %dn", clock() - t1);
}
#pragma omp task depend (in:a, b)  
{
e += E();
printf("E is finished after %dn", clock() - t1);
}
}
}
return 0;
}

最新更新