0

配列に依存する OpenACC コードを書いています。内部ループの各反復は、配列の同じ位置を更新できます。ここにいくつかのコードがあります:

    long unsigned int digits[d + 11];
    for (long unsigned int digit = 0; digit < d + 11; ++digit)
            digits[digit] = 0;

    for (long unsigned int i = 1; i <= n; ++i) {
            long unsigned int remainder = 1;
            for (long unsigned int digit = 0; digit < d + 11 && remainder; ++digit) {
                    long unsigned int div = remainder / i;
                    long unsigned int mod = remainder % i;
                    digits[digit] += div; // here
                    remainder = mod * 10;
            }
    }

OpenMP版は以下のように書いていました。

    #pragma omp parallel private(i)
    {
            long unsigned int digit_local[d+11];
            for(i=0;i<d+11;i++)
                    digit_local[i] = 0;

            #pragma omp for
            for (i = 1; i <= n; ++i) {
                    long unsigned int remainder = 1;
                    for (long unsigned int digit = 0; digit < d + 11 && remainder; ++digit) {
                            long unsigned int div = remainder / i;
                            long unsigned int mod = remainder % i;
                            digit_local[digit] += div;
                            remainder = mod * 10;
                    }
            }

            #pragma omp critical
            for(long unsigned int digit = 0; digit < d+11; ++digit)
                    digits[digit] += digit_local[digit];

    }

OpenACC では、キーワード private は配列で機能しますが、プライベート配列をグローバル配列と結合する方法がわかりません。

ありがとう。

4

1 に答える 1

0

OpenACC の「アトミック アップデート」ディレクティブを使用します。

            #pragma acc atomic update
            digits[digit] += div; // here

または、OpenMP バージョンと同様のことを行うこともできます。

    long unsigned int digit_local[d+11][n];
    #pragma acc data create(digit_local) copyout(digits)
    {

    #pragma acc parallel loop gang vector
    for (i = 1; i <= n; ++i) {
          for(j=0;j<d+11;j++) digit_local[j][i] = 0;
            long unsigned int remainder = 1;
            for (long unsigned int digit = 0; digit < d + 11 && remainder; ++digit) {
                    long unsigned int div = remainder / i;
                    long unsigned int mod = remainder % i;
                    digit_local[digit][i] += div;
                    remainder = mod * 10;
            }
    }

    #pragma acc parallel loop gang
    for(long unsigned int digit = 0; digit < d+11; ++digit) {
          long unsigned int dsum = 0;
          #pragma acc loop vector reduction(+:dsum)
          for (i = 1; i <= n; ++i) {
            dsum += digit_local[digit][i];
          }
          digits[digit] = dsum;
    }
    }

ただし、これで速度が向上するかどうかはわかりません。

これが役に立てば幸いです、マット

于 2016-09-21T15:28:47.600 に答える