2

ネストされた for ループを並列化するために再コーディングしようとすると問題が発生します。

for(i=0; i<n; i++)
{
    for(j=0; j<n; j++)
    {
        if(asubsref(struct1,j) > 0)
            asubsref(struct2,j) = asubsref(struct3,j) + 1;
    }
    for(j=0; j<n; j++)
        asubsref(struct1,j) = asubsref(struct2,j) - asubsref(struct3,i);
}

Struct1/struct2 は、それぞれ width/height/int-float 配列を持つ 2 つの構造体です。struct3 は float 構造体です。

これまでの私の試みは、それらを 2 つの異なるループにすることでしたが、残念ながら、多くの間違った結果が得られるため、うまくいきませんでした。

#pragma omp parallel
{
#pragma omp for private(j)
   for(i=0; i<n; i++)
   {
     for(j=0; j<n; j++)
     {
       if(asubsref(struct1,j) > 0)
         asubsref(struct2,j) += 1;
     }
   }
#pragma omp for private(j)
   for(i=0; i<n; i++)
   {
     k = asubsref(struct3,i);
     for (j=0; j<n; j++)
     {
       asubsref(struct1,j) -= k;
     }
   }
}

私は答えを探しているわけではありませんが、これについてどうやって行くかを考えるのに役立つガイダンス/答えへのヒントなどを探しています。

4

1 に答える 1

4

このコードに表示されるのは、次の 3 つの配列です。

array1: asubsref(seed,0) ... asubsref(seed,n-1)
array2: asubsref(bin,0) ... asubsref(bin,n-1)
array3: asubsref(w,0) ... asubsref(w,n-1)

この仮定が正しく、asubsref が副作用を生じない場合、次の不変条件を導出できます。

ループの実行の終了後、array2[j] は、0 から x までの i に対する array3[i] の合計が array1[j] よりも小さくなるような最大数である x の数だけインクリメントされます。

これがあなたができることです。まず、2 つの最も内側のループをマージできます。これは、(私たちの仮定では) 反復が独立しているためです。

for(i=0; i<n; i++)
{
    for(j=0; j<n; j++)
    {
        if(asubsref(seed,j) > 0)
            asubsref(bin,j) = asubsref(bin,j) + 1;
        asubsref(seed,j) = asubsref(seed,j) - asubsref(w,i);
    }
}

次に、最も内側のループと最も外側のループを交換します

for(j=0; j<n; j++)
{
   for(i=0; i<n; i++)
   {
        if(asubsref(seed,j) > 0)
            asubsref(bin,j) = asubsref(bin,j) + 1;
        asubsref(seed,j) = asubsref(seed,j) - asubsref(w,i);
   }
}

次のコードが機能することは明らかです

#pragma omp parallel for (private i)
for(j=0; j<n; j++)
{
   for(i=0; i<n; i++)
   {
        if(asubsref(seed,j) > 0)
            asubsref(bin,j) = asubsref(bin,j) + 1;
        asubsref(seed,j) = asubsref(seed,j) - asubsref(w,i);
   }
}

ループを分割すると、明らかに不変式が壊れます。

于 2012-05-23T12:38:15.630 に答える