OpenMP Producer-Consumer意外结果 [英] OpenMP Producer-Consumer unexpected result

查看:90
本文介绍了OpenMP Producer-Consumer意外结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用C语言中的OpenMP解决一个简单的生产者-消费者问题.

I am working on a simple producer-consumer problem, using OpenMP in C.

我的程序创建了4个线程,其中两个是使用者,两个是生产者.每个生产者将字符放置在缓冲区中,而消费者仅打印该字符.

My program creates 4 threads, two of which are consumers and two producers. Each producer places a character in a buffer, and the consumers just print the character.

我的目的是使生产者/消费者同步,以便每个生产者将产生字母的下一个顺序字符,并且每个消费者将打印放置在缓冲区中的下一个顺序字符.

My aim is to synchronize the producers/consumers so that each producer will produce the next in order character of the alphabet and each consumer will print the next in order character that is placed in the buffer.

这是我的代码:

#include <stdio.h>
#include <unistd.h>
#include <omp.h>

#define SIZE 5
#define NUMITER 26


char buffer[SIZE];
int nextin = 0;
int nextout = 0;
int count = 0;
int empty = 1;
int full = 0;
int i,j;

void put(char item)
{
    buffer[nextin] = item;
    nextin = (nextin + 1) % SIZE;

    count++;
    if (count == SIZE)
        full = 1;
    if (count == 1) // buffer was empty
        empty = 0;
}


void producer(int tid)
{
    char item;
    while( i < NUMITER)
    {
        #pragma omp critical
        {
            item = 'A' + (i % 26);
            put(item);
            i++;
            printf("%d Producing %c ...\n",tid, item);
        }
        sleep(1);
    }
}


char get()
{
    char item;

    item = buffer[nextout];
    nextout = (nextout + 1) % SIZE;
    count--;
    if (count == 0) // buffer is empty
        empty = 1;
    if (count == (SIZE-1))
        // buffer was full
        full = 0;
    return item;
}


void consumer(int tid)
{
    char item;
    while(j < NUMITER )
    {
        #pragma omp critical
        {
            j++;
            item = get();
            printf("%d ...Consuming %c\n",tid, item);
        }
    sleep(1);
    }
}

int main()
{
    int tid;
    i=j=0;
    #pragma omp parallel firstprivate(i,j) private(tid) num_threads(4) 
    {
       tid=omp_get_thread_num();

       if(tid%2==1)
       {
           producer(tid);
       }
       else
       {
           consumer(tid);
       }
    }
}

这是输出:

0 Producing A ...
2 Producing B ...
1 ...Consuming A
3 ...Consuming B
1 ...Consuming  <---- notice empty
0 Producing C ...
3 ...Consuming  <---- notice empty
2 Producing D ...
2 Producing E ...
3 ...Consuming E
0 Producing F ...
1 ...Consuming F
2 Producing G ...
3 ...Consuming G
0 Producing H ...
1 ...Consuming H
3 ...Consuming D
2 Producing I ...
0 Producing J ...
1 ...Consuming J
3 ...Consuming F
2 Producing K ...
0 Producing L ...
1 ...Consuming L
3 ...Consuming H
2 Producing M ...
0 Producing N ...
1 ...Consuming N
3 ...Consuming J
2 Producing O ...
0 Producing P ...
1 ...Consuming P
3 ...Consuming L
2 Producing Q ...
0 Producing R ...
1 ...Consuming R
2 Producing S ...
3 ...Consuming S
0 Producing T ...
1 ...Consuming T
3 ...Consuming P
2 Producing U ...
0 Producing V ...
1 ...Consuming V
2 Producing W ...
3 ...Consuming W
0 Producing X ...
1 ...Consuming X
2 Producing Y ...
3 ...Consuming Y
0 Producing Z ...
1 ...Consuming Z

那些没有打印字符的空行表明我没有实现应有的同步. 我想念什么?

Those empty lines that have not printed a character indicate that I dont achieve the synchronization that I should. What am I missing?

在此先感谢您的帮助或想法.

Thank you in advance for any help or ideas.

推荐答案

所以@Jlghtuse是正确的,存在数据争用,这是因为关键区域的声明错误.

So @Jlghtuse was correct, there were data races and that was because of mistaken declarations of the critical areas.

您看到我宣布了我的关键领域:

You see I declared my critical areas:

void consumer(int tid)
{
    char item;
    while(j < NUMITER )
    {
        #pragma omp critical
        {
            j++;
            item = get();
            printf("%d ...Consuming %c\n",tid, item);
        }
    sleep(1);
    }
}

void producer(int tid)
{
    char item;
    while( i < NUMITER)
    {
        #pragma omp critical
        {
            item = 'A' + (i % 26);
            put(item);
            i++;
            printf("%d Producing %c ...\n",tid, item);
        }
        sleep(1);
    }
}

这导致消费者无法进入其他消费者的关键区域,而产品却拥有进入的区域,反之亦然.解决方案非常简单,我只需要为关键区域添加一个通用名称,现在对于消费者而言,关键区域对生产者来说也至关重要,反之亦然.

That resulted in consumers not having access into other consumers critical area but produces had and vice versa. The solution was rather simple, I just had to add a common name for the critical areas and now a critical area for a consumer is critical for a producer too, and vice versa.

这是声明关键区域的正确代码:

This is the correct code for declaring the critical areas:

#pragma omp critical (CRIT)

这篇关于OpenMP Producer-Consumer意外结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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