2016-11-11 7 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を渡す方法です。別の反復には異なる値が必要なので、それらを共有することはできません。したがって、1つの方法は、繰り返しを奇数と偶数に分けることですが、それは非常に非効率的です。

この場合のご提案はありますか?

+0

する減速句最初は「1」または「-1」、記号/(2 * i + 1) 'は、最初の反復を除くすべてに対して' 0 'を与えます。また、私がOMPについて知らないうちに、「サイン」をプライベートと共有の両方として宣言することは、私と矛盾しているようです。 – celtschk

+0

サインプライベートとシェアは間違いでした。私はここで自分のコードを修正しました。 – algoProg

+0

「pi = 4」という結果が間違っていますか? – celtschk

答えて

2

円の近似にはLeiniz formulaを使用してみてください。

  • C++でスコープの反復が宣言されているため、プライベートからiを削除します。用

    (unsigned int型i = 0; I < 10000; I ++)

  • 符号はIの奇数/偶数プロパティ上のベースを知っているので、(iは& 1)の代わりにチェック使用してから符号を削除することができますプライベート

    int sign = 1 - (i & 1); 
        pi += (sign == 1 ? 1f : -1f)/(2 * i + 1); 
    
  • pioldは、最終結果のパイに影響を与えるあなたはを読むことができるプライベート

から削除されることはありません詳しくはをご覧ください。私はコンパイラがOpenMPをサポートしていないので、私はテストすることができず、サンプルコードを与えることができません。しかし、私は2つのケースを提案します:

  • openmpセクションを使用してiの奇数/偶数で2つのスレッドに式を分けます(+)と( - )。 2つのセクションがあります。

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; 
  • 使用i`は整数変数と `の両方である` `仮定sign`およびPI
+0

返信いただきありがとうございます。私はいくつかのコード修正(共有リスト)を行い、反復回数が増えるにつれ、よりよい結果を得ました。私はループ内のサインの状態をチェックする方法を理解しようとしています。 – algoProg