#pragma omp flush在线程之间建立交换数据

你写了一个非常简单的例子,说明如何使用omp flush来交换数据,以生产者 – >消费者的方式,在线程中我发现了一个有趣的行为。

int a=-1; int flag=1; int count=0; #pragma omp parallel num_threads(2) { int TID; TID=omp_get_thread_num(); #pragma omp sections { #pragma omp section /////////// Producer { for(int i=0; i<9;i++) { a=i; #pragma omp flush(a) flag=1; printf("Producer a: %d flag:%d TID %d \n",a,flag,TID); while(flag) { #pragma omp flush(flag) } } flag=2; #pragma omp flush(flag) } // end producer #pragma omp section /////////// Consumer { while(1) { count++; flag=0; while(!flag) { #pragma omp flush(flag) } #pragma omp flush(a) printf("Consumer a: %d Flag: %d count %d TID %d \n",a,flag,count,TID); if (flag==2) break; // no more data } // end while(1) }// end consumer }// end sections 

使用这个非常简单的代码将产生错误的输出:生产者a:0标志:1 TID 0
制作人a:1标志:1 TID 0
消费者a:1标志:1个计数1个TID 1
制作人a:2标志:1 TID 0
消费者a:2标志:1计数2 TID 1
制作人a:3标志:1 TID 0
消费者a:3标志:1计数3 TID 1
制作人a:4标志:1 TID 0
消费者a:4标志:1计数4 TID 1
制作人a:5标志:1 TID 0
消费者a:5标志:1计数5 TID 1
制作人a:6标志:1 TID 0
消费者a:6标志:1计数6 TID 1
制作人a:7标志:1 TID 0
消费者a:7标志:1计数7 TID 1
制作人a:8标志:1 TID 0
消费者a:8标志:1计数8 TID 1
消费者a:8标志:2计数9 TID 1

错误是消费者忽略了产生a = 0的第一个数据。 如果我只是颠倒了部分的顺序,让生产者成为线程1然后一切都好……生产者a:0标志:1 TID 1
消费者a:0标志:1计数1 TID 0
制作人a:1标志:1 TID 1
消费者a:1标志:1计数2 TID 0
……我的错误是什么?

…..在与Ejd进行有趣的讨论之后(感谢),代码被编辑为:

 int a=-1; int flag=0; int count=0; #pragma omp parallel num_threads(2) { int TID; TID=omp_get_thread_num(); #pragma omp sections { #pragma omp section /////////// Consumer { while(1) { count++; if (flag) printf("Consumer a: %d Flag: %d count %d TID %d \n",a,flag,count,TID); flag=0; while(!flag) { #pragma omp flush(flag) } if (flag==2) break; // no more data } // end while(1) }// end consumer #pragma omp section /////////// Producer { for(int i=0; i<9;i++) { a=i; printf("Producer a: %d flag:%d TID %d \n",a,flag,TID); flag=1; while(flag) { #pragma omp flush(flag,a) } } flag=2; #pragma omp flush(flag) } // end producer }// end sections 

现在效果很好。 谢谢 !

不幸的是,使用flush比初看起来要复杂得多。 即使是OpenMP的专家也无法正确使用它。 问题的一部分是,列表的刷新定义很糟糕。 基本上它是允许移动的,所以如果你有一个forms的序列:

 a = ... #pragma omp flush(a) b = ... #pragma omp flush(b) 

冲洗(a)必须在设置a之后,但可以在设置和冲洗(b)之后移动。 它必须在下次使用之前发生。

在任何情况下,执行所需操作的最佳方法是在没有列表的情况下使用flush,并在您感兴趣的每个变量集之后执行刷新,并在读取您感兴趣的每个变量之前执行刷新。

另一个问题是你没有正确交接。 您不能在消费者中为生产者设置标志,以便在消费者实际消费所产生的价值之后生成另一个数字。