#pragma omp flush使线程之间交换数据 [英] #pragma omp flush to make exchange data among threads

查看:541
本文介绍了#pragma omp flush使线程之间交换数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好,我写了一个非常简单的示例,其中介绍了如何使用omp flush以生产者-消费者方式在线程之间交换数据,我发现一个有趣的行为.

Hi writing a very simple example on how to use omp flush to exchange data, in a producer-> consumer way,among threads I have found a funny behavior.

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 count 7 TID 1
生产者a:8标志:1 TID 0
消费者a:8个标志:1个计数8个TID 1
消费者a:8标志:2计数9 TID 1

Using this very simple code will produce an erroneous output: Producer a: 0 flag:1 TID 0
Producer a: 1 flag:1 TID 0
Consumer a: 1 Flag: 1 count 1 TID 1
Producer a: 2 flag:1 TID 0
Consumer a: 2 Flag: 1 count 2 TID 1
Producer a: 3 flag:1 TID 0
Consumer a: 3 Flag: 1 count 3 TID 1
Producer a: 4 flag:1 TID 0
Consumer a: 4 Flag: 1 count 4 TID 1
Producer a: 5 flag:1 TID 0
Consumer a: 5 Flag: 1 count 5 TID 1
Producer a: 6 flag:1 TID 0
Consumer a: 6 Flag: 1 count 6 TID 1
Producer a: 7 flag:1 TID 0
Consumer a: 7 Flag: 1 count 7 TID 1
Producer a: 8 flag:1 TID 0
Consumer a: 8 Flag: 1 count 8 TID 1
Consumer a: 8 Flag: 2 count 9 TID 1

错误是使用者忽略了产生的第一个基准a = 0. 如果我只是简单地反转各节的顺序,让生产者为线程1,那么一切都很好...... 生产者a:0标志:1 TID 1
使用者a:0标志:1 count 1 TID 0
生产者a:1标志:1 TID 1
使用者a:1个旗标:1个计数2个TID 0
.... 我的错是什么?

The error is that the first datum produced a=0 is ignored by the consumer. If I simply invert the order of the sections, letting the producer be thread 1 then everything is ok..... Producer a: 0 flag:1 TID 1
Consumer a: 0 Flag: 1 count 1 TID 0
Producer a: 1 flag:1 TID 1
Consumer a: 1 Flag: 1 count 2 TID 0
.... Whats my mistake ?

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

..... After the interesting discussion with Ejd (thanks) the code was edited to:

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    

现在效果很好.谢谢!

推荐答案

不幸的是,使用冲洗功能比乍看起来要复杂得多.即使是OpenMP的专家,也无法尝试正确使用它.问题的一部分是,与列表刷新的定义不正确.基本上允许移动,所以如果您有以下形式的序列:

Unfortunately using flush is a lot more complicated than it seems at first glance. Even the experts in OpenMP have trouble trying to use it correctly. Part of the problem, is that flush with a list is badly defined. Basically it is allowed to move, so if you have a sequence of the form:

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

flush(a)必须在设置a之后,但是可以在set和flush(b)之后移动.它只是必须在下一次使用a之前发生.

the flush(a) has to be after the setting of a, but could be moved after the set and flush(b). It just has to occur before the next use of a.

无论如何,最好的方法是使用flush 不使用列表,并在您感兴趣的每组变量之后进行刷新,然后在刷新之前进行刷新.读取您感兴趣的每个变量.

In any case, the best way to do what you want, is to use flush without a list and do the flush after every set of a variable that you are interested in and do a flush before the read of every variable you are interested in.

另一个问题是您没有正确地进行交接.您不能在消费者中设置标志,直到生产者实际消费了所产生的价值之后,生产者才能生成另一个数字.

The other problem is that you are not handing off correctly. You can't set the flag in the consumer for the producer to generate another number until after the consumer has actually consumed the value produced.

这篇关于#pragma omp flush使线程之间交换数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆