0

単純な並列加算器。配列の最初の要素へのポインター、配列の最後の要素へのポインター、最初のポインターの要素番号、および操作されている配列のこの部分の要素の数を渡します。

    double my_func (double *x, double *x_last, int first_pos, int n)
    {
      if (n ==1) {
        return x[first_pos];
      }
      else if (n == 2) {
        return x[first_pos] + x[first_pos+1];
      }
      else {
        double x1,x2;

        x1 = _Cilk_spawn my_func (&x[first_pos], &x[n/2+first_pos-1],first_pos, n/2);
        x2 = my_func (&x[n/2+first_pos],&x[first_pos+n-1],n/2+first_pos, n-n/2);
        _Cilk_sync;

        return x1 + x2;
      }
    }

サイズ80の配列から始めたとしましょう。これは、要素#0-19(第1四半期)で完全に機能し、要素#20-39以降のすべての要素に対して0の束/ガベージを返します。明らかにx1とx2の両方の線がある程度機能していますが、関数が機能しなくなっており、その理由はわかりません。何か案は?

4

1 に答える 1

3

配列を間違ってスライスしています:

x1 = my_func (&x[n/2+first_pos],&x[first_pos+n-1],n/2+first_pos, n-n/2);
                    ^                                 ^
            new "base" pointer                first pos in slice?!

調整されたポインタをスライスの最初の要素その要素のグローバルインデックスの両方に渡すことはできません。いわば、インデックスを複数回作成することになり、無効なアドレスが逆参照されることになります。

の場合n = 80、2番目の再帰呼び出しはx要素を指すように渡されます&x[80/2+0]。つまり&x[40]、ですが、その呼び出しに対しても設定first_pos40れます。最終的には、に到達しn < 3、累積を使用してインデックスを作成しfirst_posます。

また、わかりやすくするために、入力データはconst読み取り専用の場合に使用する必要があります。

于 2013-02-12T11:25:27.940 に答える