0

Fortran で書かれたシーケンシャル コードには、次のように動作するいくつかのベクトルをシャッフルするサブルーチンがあります。

    DO i=1,nsim

      IF(iflag(i) == 0)THEN

        j=j+1
        pos(j)=pos(i)
        v(j)=v(i)
        iflag(j)=iflag(i)

      END IF

    END DO
    nsim=j

私は初心者の OpenMP ユーザーなので、このループを正しい方法で記述する方法がわかりません。当初、私は次のようなことを考えました:

!$omp parallel do reduction(+: j)
  DO i=1,nsim

  IF(iflag(i) == 0)THEN

    j=j+1
    pos(j)=pos(i)
    v(j)=v(i)
    iflag(j)=iflag(i)

  END IF

END DO
!$omp end parallel do
nsim=j

しかし、この方法で競合状態を生成できるかどうかはわかりません。このループをより適切に記述する方法について何か提案はありますか? 前もって感謝します

4

1 に答える 1

1

この種のループを並列化するには、次のようにします。

  1. 一連の 1 と 0 に対して「prefix-sum」操作を使用します。THEN が取得された場合、シーケンス要素は 1 であり、それ以外の場合は 0 です。プレフィックスサムの結果は、各反復の j の値を示します。
  2. 手順 1 の j 値を使用して、左辺を一時配列に置き換えて THEN アクションを実行します。
  3. 一時配列を元の配列にコピーします。

「プレフィックスサム」の実装の詳細については、並列プレフィックスサムの説明を参照してくださいステップ 2 は、プレフィックスサムの「ダウンスイープ」フェーズに埋め込むことができます (他の説明を参照)。プレフィックスサムは帯域幅の消費を 2 倍にするため (これは 2 パス アルゴリズムであるため)、高速化を実現することは困難です。

于 2013-06-20T20:21:01.513 に答える