2016-11-11 90 views
1

我有以下代碼,這是導致錯誤的輸出。OpenMP:減少和共享

#pragma omp parallel private(i,piold) shared(pi,sign) 
{ 
#pragma omp for reduction(+:pi) schedule (static) 
    for (i = 0; i < 100000; i++){ 
     piold = pi; 
     pi += sign/(2*i+1); 
     sign=-sign; 
    } 
} 
    pi = 4*pi; 

由於我是OpenMP的新手,我有點迷惘。令我困惑的是如何在線程之間傳遞sign,pipiold?由於替代迭代需要不同的值,因此它們不能共享。所以有一種方法是將迭代分爲奇數和偶數,但這似乎效率很低。

在這種情況下的任何建議?

+0

假設'sign'和'i'均爲整數變量和' sign'最初是'1'或'-1','sign /(2 * i + 1)'除了第一次迭代外''會給所有人提供'0'。另外,雖然我不瞭解OMP,但將「sign」聲明爲私密和共享似乎與我相矛盾。 – celtschk

+0

簽名私人和分享是一個錯誤。我在這裏更正了我的代碼。 – algoProg

+0

您得到「pi = 4」的結果是錯誤的嗎? – celtschk

回答

2

看起來像你試圖使用Leiniz formula近似pi。

  • C++支持聲明迭代範圍,所以將我從私有中刪除。

    爲(無符號整數,I = 0;我< 10000;我++)

  • 符號可以知道在奇/偶我的屬性的基礎上,所以使用(ⅰ& 1)檢查來代替,而從除去符號私人

    int sign = 1 - (i & 1); 
        pi += (sign == 1 ? 1f : -1f)/(2 * i + 1); 
    
  • piold不會影響最終結果PI,從私人

刪除您可以閱讀http://bisqwit.iki.fi/story/howto/openmp/瞭解更多信息。由於我現在沒有編譯器支持OpenMP,因此我無法測試並給出示例代碼。但我建議兩種情況:

  • 公式將(+)和( - )分成2個線程奇數/偶數我使用openmp節。您將有兩個部分

double plus = 0.0;

for (int i = 0; i < 5000; i++) 
     plus += (4 * i + 1); 

double minus = 0.0; 
for (int i = 0; i < 5000; i++) 
    minus += (4 * i + 3); 

然後

pi = plus - minus; 
  • 使用還原子句PI
+0

謝謝你的回覆。我做了一些代碼修改(共享列表),隨着迭代次數的增加,我得到了更好的結果。我試圖瞭解如果有條件檢查循環內的符號。 – algoProg