OpenMP Producer-Consumer unexpected result

≯℡__Kan透↙ 提交于 2019-12-23 20:12:36

问题


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

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.

This is my code:

#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);
       }
    }
}

And this is the output :

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.


回答1:


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);
    }
}

and

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)


来源:https://stackoverflow.com/questions/20041030/openmp-producer-consumer-unexpected-result

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!