2017-02-12 88 views
0
int count1(testcase *testcases, int n) { 
    int i; 
    int count = 0; 
    #pragma omp parallel for 
    for (i = 0; i < n; ++i) { 
     if (test(testcases[i]) == true) { 
     ++count; 
     } 
    } 
    return count; 
} 

有點不尋常的問題,即似乎沒有問題。 自學OpenMP for C,這是關於我正在閱讀的主題的PDF文檔。循環中缺少錯誤(OpenMP with C)

作者暗示代碼存在一些問題。給定n個測試案例,我們有一些功能測試可以對案例進行處理,並返回一個布爾值,指示測試是否成功。這段代碼應該計算測試次數。作者說,它不正確 - 我只是不明白爲什麼。一直以來,我一直試圖圍繞它思考這個問題,這可能很簡單。

我已經試圖代碼的這個用0和1的陣列的示例版本和由表達式檢查,如果它是1和計數該取代

test(testcases[i]) == true 

。但是,它正確地計算了我的1。錯誤在哪裏?

+0

正確的做法是'#pragma omp parallel for reduction(+:count)'。試試這個,看看你能否讓它有所作爲。你可以從刪除條件測試開始,然後遞增count。它應該等於'n'。 –

回答

0

這是處理,這段代碼可以執行得很好,但問題是count變量,它在並行區域外(也稱爲循環)聲明,然後在並行區域內增加。所以計數增加並行運行,這就產生了一個問題,因爲如果2個或更多線程同時嘗試增加計數,因爲相信我會發生這種情況。然後奇怪的事情會開始發生。

變量存儲在內存右側,所以爲了增加變量的值,我們需要從內存中讀取它(當前值),在CPU中增加它並將其寫回。現在我們並行運行該序列中,從而作爲一個示例中,這有時會發生(記住線程並行運行):在存儲器

  1. 計數= 2
  2. 線程1讀取計數(2)
  3. 線程2讀取數(2)
  4. 線程1度的增加和寫回計數內存變量(3)
  5. 同樣的事情不會線程2現在(寫回3)

所以我n內存我們在count變量中有3的值,但是由於兩個線程被執行,它應該是4.這就是爲什麼這個代碼不會總是工作。而這只是可能發生的事情之一。這就是爲什麼我們知道關鍵部分,信號量,互斥,...希望這有助於。

+0

謝謝!我沒有想到,但它很有意義。 – jfeis

+1

最重要的是,你應該閱讀減刑條款。由於OpenMP在沒有效率的情況下不值錢,所以您還應該考慮通過單線程simd減少比通過非simd並行減少可以更高效地實現這樣一個簡單的情況,但是您可以將它們組合起來。然後有語言特性(可能不是普通的C語言)來實現這一點,這應該在OpenMP之前考慮。 – tim18