2016-11-28 3 views
3

大きな配列のいくつかの要素を更新しています。ループを安全に並列化できることをコンパイラに伝える方法はありますか?

更新がからなる:(それはゼロではない場合)アレイ 内の新しい位置に更新された値を移動する電流値

  • をクリア
  • 10によって電流値を乗算

    私は、移動が発生したときに衝突がないことを知っています。
    ループを安全に並列化できることをコンパイラにどのように伝えることができますか?

    do i = 1, 1e6 
        if (v[i] /= 0) then 
         temp = v[i] * 10 
         v[i] = 0 
         ndx = get_move_to_ndx(i) 
         v[ndx] = temp 
        end if 
    end do 
    

    私はifortを利用していますが、これはコンパイラに依存しないと思います。

  • +8

    FortranとCの奇妙な混合物...削除された機能であるDOループの実際の最終値の使用については言及していません。 CONCURRENTは、ループが並列化に適しているが、PUREプロシージャにコールする必要があることをコンパイラに示す手がかりになります。 ifortに固有の何かを気にしなければ、!DIR $ IVDEPが役に立ちます。 –

    +1

    上記は私にとって 'python'のようなものです。 – ja72

    +1

    コンパイラが衝突がないと自動的に推測することはできません。 OpenMPを使用している場合、たとえば、共有配列を使用している場合は正常に動作します。 –

    答えて

    1

    ここでは雑種のアプローチです。そのため、一時的なベクターを使用したアイデアがあります。どこが正しいかもしれない、あなたはそれを試さなければならないでしょう。 WHERE/ELSEWHEREの主な利点は、通常はループと同じくらい速くないため、読みやすさです。読みやすくなります。

    !DIR$ SIMD 
    FillTemp: Do I = 1, 1000000 
        Temps(I) = v(I)*10 
    ENDDO FillTemp 
    
    !$OMP PARALLEL DO 
    FindIndex: Do I = 1, 1000000 
        ndx_vect(I) = get_move_to_ndx(i) 
    ENDDO FindIndex 
    
    WHERE(Temps /= 0) 
        V = 0 
    ELSEWHERE 
        v(ndx_Vect) = tempz 
    ENDWHERE 
    
    関連する問題