#pragma omplush 使线程之间交换数据

发布于 2024-10-19 06:12:03 字数 2739 浏览 3 评论 0原文

您好,编写了一个非常简单的示例,介绍如何在生产者-> 中使用 omplush 交换数据。消费者方式,在线程中我发现了一个有趣的行为。

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
Consumer a: 8 Flag: 2 count 9 TID 1

错误是产生的第一个数据a=0被consumer忽略。 如果我简单地颠倒各部分的顺序,让生产者成为线程 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    

现在工作得很好。谢谢 !

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

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

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 ?

.....
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    

That now works nicely. Thanks !

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

忘年祭陌 2024-10-26 06:12:03

不幸的是,使用flush比乍一看要复杂得多。即使是 OpenMP 专家也很难正确使用它。问题的一部分是与列表刷新的定义错误。基本上它是允许移动的,所以如果你有一个以下形式的序列:

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

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

在任何情况下,做你想做的事情的最好方法是使用没有列表的刷新,并在你感兴趣的每组变量之后执行刷新,并在读取之前执行刷新你感兴趣的每个变量。

另一个问题是你没有正确地传递。在消费者实际消费完所产生的值之前,您无法在消费者中为生产者设置标志来生成另一个数字。

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)

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.

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文