Состояние RACE в алгоритме ПЦР с OpenACC - PullRequest
0 голосов
/ 04 марта 2019

Я пытаюсь реализовать трехдиагональный алгоритм ПЦР с openACC, этот метод имеет векторный параллелизм.и вызывается через solvesolvePCR () с параллелизмом банд.когда я увеличиваю размер меша выше 256 (например, 300, ... 512), я сталкиваюсь с состоянием гонки.

 #pragma acc routine vector
    void pcr(int n, double *a, double *c, double *d)
    {

      int level = log2(n)+1;
      int s;
      double r;
      int m=512;
      int size=n/m+1;
    // these should go on register
      double a0[20];
      double a1[20];
      double a2[20];

      double c0[20];
      double c1[20];
      double c2[20];

      double d0[20];
      double d1[20];
      double d2[20];
      int index;

    #pragma acc loop seq private(a0[0:20],a1[0:20],a2[0:20],c0[0:20],c1[0:20],c2[0:20],d0[0:20],d1[0:20],d2[0:20])
      for (int p = 0; p < level; p++)
     {
       s = 1 << p;

    #pragma acc loop vector private(a0[0:20],a1[0:20],a2[0:20],c0[0:20],c1[0:20],c2[0:20],d0[0:20],d1[0:20],d2[0:20],index)
      for(int i = 0; i < n ; i++) {

        index=i/m;

          if (i - s < 0 && i + s < n) { 
            a0[index]=a[i];
            a1[index]=0.0;
            a2[index]=a[i+s];

            c0[index]=c[i];
            c1[index]=0.0;
            c2[index]=c[i+s];

            d0[index]=d[i];
            d1[index]=0.0;
            d2[index]=d[i+s];
          }
      else if (i + s >= n && i - s >= 0)
         {
            a0[index]=a[i];
            a1[index]=a[i-s];
            a2[index]=0.0;

            c0[index]=c[i];
            c1[index]=c[i-s];
            c2[index]=0.0;

            d0[index]=d[i];
            d1[index]=d[i-s];
            d2[index]=0.0;
        }
          // both indices are ok to assign
          else
          {
            a0[index]=a[i];
            a1[index]=a[i-s];
            a2[index]=a[i+s];

            c0[index]=c[i];
            c1[index]=c[i-s];
            c2[index]=c[i+s];

            d0[index]=d[i];
            d1[index]=d[i-s];
            d2[index]=d[i+s];
         }
       }

      // both indices are ok to assign    
    #pragma acc loop vector  private(a0[0:20],a1[0:20],a2[0:20],c0[0:20],c1[0:20],c2[0:20],d0[0:20],d1[0:20],d2[0:20],index,r)
         for(int i=0;i<n;i++)
         {
            index=i/m;
            r = 1. / (1. - a0[index] * c1[index] - c0[index] * a2[index]);
            a[i] = -r * a0[index] * a1[index];
            c[i] = -r * c0[index] * c2[index];
            d[i] = r * (d0[index] - a0[index] * d1[index] - c0[index] * d2[index]);
         }
        }
    }

и вызывается из параллельного цикла банды.

#pragma acc routine gang
void solvePCR( const int index )
{
    double eig; 
    int count = 0; 
    int i, j;

  for ( int j = 0; j < nxChunk; j++ )
    {    
#pragma acc loop private(eig)
        for ( int i = 0; i < nyChunk; i++ )
        {    
          T.pcr(nz, crpcr_lower+nz*i, crpcr_upper+nz*i,crpcr_rhs+nz*i  );
        }
  }
}

1 Ответ

0 голосов
/ 05 марта 2019

Мое лучшее предположение заключается в том, что длина вашего вектора равна 256, поэтому, если вы превысите это значение, у вас будет несколько банд.Поскольку цикл «j» в solvePCR не имеет директивы цикла, он будет работать в режиме «избыточности банды», то есть все банды будут выполнять все итерации «j».

Предполагая, что вы вызываете эту процедуру из «параллельного» региона, попробуйте добавить «num_gangs (1)».

#pragma acc parallel num_gangs(1)
{
    solvePCR(index);
}

Если я прав, состояние гонки должно исчезнуть.

Если нет, можете ли вы опубликовать полный пример воспроизведения?

...