您正在编写一个关于如何使用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
现在效果很好。谢谢!
答案 0 :(得分:5)
不幸的是,使用同花顺比初看起来要复杂得多。即使是OpenMP的专家也无法正确使用它。问题的一部分是,列表的刷新定义很糟糕。基本上它是允许移动的,所以如果你有一个形式的序列:
a = ...
#pragma omp flush(a)
b = ...
#pragma omp flush(b)
冲洗(a)必须在设置a之后,但可以在设置和冲洗(b)之后移动。它必须在下次使用之前发生。
在任何情况下,做你想要的最好的方法是使用flush 而不用列表,并在你感兴趣的每一组变量之后进行刷新并在之前进行刷新阅读您感兴趣的每个变量。
另一个问题是你没有正确交接。您不能在消费者中为生产者设置标志,以便在消费者实际消费所产生的价值之前生成另一个数字。