OpenMP - Zrównoleglenie zagnieżdżonej pętli

0

Witam.

Próbuję zrównoleglić taką oto pętlę:

 for (j=0; j < n; j++)   
	for (i=0; i < j; i++)
            for (k=0; k < n; k++)
				 R[i][j] = R[i][j] + A[k][j]*Q[k][i];

poprzez dodanie dyrektywy:

#pragma omp parallel for private(j, i, k) shared (A, Q, R)
 

A, Q oraz R to macierze (tablice typu double).
Niestety operacja zrównoleglona daje bezsensowne wyniki. Patrzę na to i ciągle nie widzę dlaczego...
dodam, że jestem początkujący w OpenMP - może ktoś mógłby mnie oświecić w czym jest problem ?

Pozdrawiam.

0

Serwis Wróżka.pl podpowiada, że w ww poście może brakować szczegółów opisu błędu.

0
Giewont88 napisał(a):

...

Błaszczyk czy Karbowski?

0

spróbuj tak:

 

#pragma omp parallel private(i,k) 
 {
#pragma omp for 
for (j=0; j < n; j++)   
        for (i=0; i < j; i++)
            for (k=0; k < n; k++)
                                 R[i][j] += A[k][j]*Q[k][i];
}
 
0

Przebudowałem trochę potrzebny mi algorytm (chodzi o operacje na macierzach), teraz całość wygląda w ten sposób (poprzednio podawałem tylko najistotniejszy fragment):

    #pragma omp parallel for private(k, i, j) shared(a, q, r, n)
    for (k=0; k<n; k++)
    {
          r[k][k]=0;
          for (i=0; i<n; i++)
              r[k][k] = r[k][k] + a[i][k] * a[i][k];
          r[k][k] = sqrt(r[k][k]);  // ||a||
         
         for (i=0; i<n; i++)
          {   
              q[i][k] = a[i][k]/r[k][k];
          }   

         for(j=k+1; j<n; j++)
         {
            r[k][j]=0;
            for(i=0; i<n; i++)
             r[k][j] += q[i][k] * a[i][j];
            for (i=0; i<n; i++)
             a[i][j] = a[i][j] - r[k][j]*q[i][k];
          }
    }

Niestety wersja zrównoleglona nadal działa źle - wyniki są liczbowo zupełnie inne niż w wersji sekwencyjnej (która na pewno liczy poprawnie).
Udało mi się "wyłapać", że problematycznym fragmentem jest:

    for (i=0; i<n; i++)
    {   
              q[i][k] = a[i][k]/r[k][k];
    }

Jeśli ktoś rozumie w czym tkwi błąd i potrafi mi to wyjaśnić / poprawić kod to bardzo proszę o pomoc.

0
  • podaj więcej kodu (np. deklaracje tablic)
  • jak na dłoni widać że czytasz a[0][0] przed wypełnieniem tego elementu
  • jeśli chcesz usunąć wszystkie tego rodzaju błędy to zrób przed wszystkimi pętlami:
#define HEX_WATCHDOG 0xffaa

#ifdef _DEBUG
#define ARR_CHECK(v,a,b) assert(v[a][b] != HEX_WATCHDOG)
#else
#define ARR_CHECK(v,a,b)
#endif

for(int i=0; i < n ; i++)
  for(int j=0; j < n; j++)
  {
     a[i][j] = r[i][j] = q[i][j] = HEX_WATCHDOG;  
  }

a potem wewnątrz każdej pętli:

zamiast:

for(i=0; i<n; i++)
             r[k][j] += q[i][k] * a[i][j];

napisz sprawdzania dla wszystkich odczytów:

for(i=0; i<n; i++) {
  ARR_CHECK(q,i,k);
  ARR_CHECK(a,i,j);
  r[k][j] += q[i][k] * a[i][j];
}

Ten test powinien wywalić błędy także w wersji sekwencyjnej.

Uwaga: wartość 0xffaa powinna być dobrana tak, żebyś był pewien że normalnie w tablicach nie występuje.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.