2011-02-24 23 views
3

您好,編寫一個非常簡單的例子,說明如何使用omp flush來交換數據,以生產者 - >消費者的方式,在線程間發現一個有趣的行爲。#pragma 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 

使用這個非常簡單的代碼會產生錯誤的輸出: 生產者一個:0標誌:1個TID 0
生產者一個:1標誌:1個TID 0
消費者一個:1標誌:1個計數1 TID 1
生產者一個:2標記:1個TID 0
消費者一個:2標記:1個計數2 TID 1
生產者一個:3標誌:1個TID 0
消費者一個:3標誌:1個計數3 TID 1
製片人a:4 flag:1 TID 0
消費者一個:4標誌:1個計數4 TID 1
生產者一個:5標誌:1個TID 0
消費者一個:5標誌:1個計數5 TID 1
生產者一個:6標誌:1個TID 0
消費者:6標誌:1個計數6 TID 1
生產者一個:7標誌:1個TID 0
消費者:7標誌:1個計數7 TID 1
生產者一個:8標誌:1個TID 0
消費者一個:8標誌:1計數8 TID 1
消費者a:8標誌:2計數9 TID 1

錯誤是第一個數據產生a = 0被消費者忽略。 如果我只是顛倒節的順序,讓生產者線程1,則一切正常..... 製作一個:0標誌:1個TID 1
消費者: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

小錯誤....最後輸出的第一行是開始:製作一個:0標誌:1個TID 1 – GBBL 2011-02-24 21:44:02

回答

5

不幸的是,使用flush比第一眼看起來複雜得多。即使是OpenMP專家也無法正確使用它。問題的一部分是,與列表齊平的定義不明確。基本上,它可以移動,所以如果你有以下形式的序列:

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

沖洗(一)必須的設置後,但設定後可以移動平齊(B) 。它只是在下一次使用a之前發生。

在任何情況下,最好的方法是使用flush 而不使用列表,並且在每個感興趣的變量集合之後執行flush操作,並在讀取每個變量之前執行flush操作你感興趣的變量。

另一個問題是你沒有正確地切換。您不能在消費者中爲生產者設置標誌,直到消費者實際消費所產生的價值之後才生成另一個數字。

+0

感謝你們的盛情答案....立即試圖從沖洗採取了所有的名單.. ...並且在讀取之前添加一個問題仍然存在,如果我保留了該部分的順序..... – GBBL 2011-02-24 23:44:32

+0

試圖將flag = 0 .... flush在printf之後。這解決了這個問題,如果消費者是線程1,但問題仍然存在(甚至更糟糕),如果消費者是線程0 .....再次感謝.... – GBBL 2011-02-25 00:03:09

+0

我能夠稍微修改您的代碼並使其工作。由於這常常是一個家庭作業問題,我不想只發布代碼。仔細看看你與國旗的「握手」並加以貫徹。現在的問題是你的代碼。如果你看不到它,請發佈你的新代碼,我會嘗試給你一個進一步的提示。 – ejd 2011-02-25 01:23:55