Segfault для параллельной петли omp - PullRequest
0 голосов
/ 11 мая 2019

У меня есть 2d массив с плавающей точкой, и я хочу отсортировать индексы каждой строки.Я использую функцию для сортировки.Я зацикливаюсь на строках массива и вызываю функцию сортировки для каждой строки.Я просто хочу, чтобы этот вызов функции выполнялся параллельно.Серийная версия работает отлично.Но когда я использую omp параллельно, я получаю segfault.Я попытался приватизировать переменные и сделать несколько циклов критическими, я до сих пор не могу понять причину этой ошибки.Любая помощь могла бы быть полезна.

Ниже приведен мой код:

#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
void QuickSort(float A[], size_t I[], size_t lo, size_t hi)
{
   while (lo < hi)
   {
      float pivot = A[I[lo + (hi - lo) / 2]];
      size_t t;
      size_t i = lo - 1;
      size_t j = hi + 1;
      while (1)
      {
         while (A[I[++i]] < pivot);
         while (A[I[--j]] > pivot);
         if (i >= j)
            break;
         t = I[i];
         I[i] = I[j];
         I[j] = t;
      }
    /* avoid stack overflow */
      if((j - lo) < (hi - j)){
         QuickSort(A, I, lo, j);
         lo = j+1;
      } else {
         QuickSort(A, I, j + 1, hi);
         hi = j;
      }
   }
}
//Declare number of data points
#define COUNT (10)             

int main(int argc, char**argv)
{
   int  i,j;
   //Index array for every row
   size_t I[COUNT] ;
   //Array to keep first 5 sorted indices for every row
   size_t I_sorted[COUNT][5];
   //Array to fill random values, and random float variable        
   float fr, A[COUNT][COUNT], B[COUNT] ;
   srand((unsigned)time(NULL));

   //Fill random float 2d array  of COUNT*COUNT dimentions
   for(i = 0; i < COUNT; i++) {         // array of indexes
      for(j=0; j<COUNT ;j++){
         fr =  (float)rand()/RAND_MAX;
         A[i][j] = fr;
         printf("%f\t",A[i][j]);
        }
        printf("\n");
   }

   //Need to call QuickSort count number of times in parallel
   #pragma omp parallel for private(j)
   for(i=0 ;i<COUNT; i++) {
   //#pragma omp critical
   //Assign a row of A to B to pass for sorting, also make index array
      for(j=0 ;j<COUNT; j++) {
         B[j] = A[i][j];
         I[j] = j;
      }
      //Sort row indices
      QuickSort(B, I, 0, COUNT-1);
      //#pragma omp critical
      //Store sorted indices
         for(j=0;j<4; j++) {
            I_sorted[i][j] = I[j];
            //printf("%d\t",I_sorted[i][j]);
         }
      //printf("\n");
    }

    //Verify sorted array is correct
    printf("------------------------\n");
    for(i = 0; i < COUNT; i++) {
       for(j = 0; j < 4; j++) {
          printf("%d\t",I_sorted[i][j]);
       }
       printf("\n");
    }

    return(0);
    }

Серийный код работает нормально, но компиляция с помощью fopenmp дает ошибку segfault.

1 Ответ

0 голосов
/ 12 мая 2019

Давайте рассмотрим случай двух потоков. Цикл for(i=0; i<COUNT; i++) будет разделен на две части: один поток будет работать для i значений в диапазоне 0 ... COUNT/2, а второй будет работать для i значений в COUNT/2+1 ... COUNT диапазон. Оба потока будут выполняться в одно и то же время, и у вас не должно быть никакой области совместно используемой памяти для записи из обоих потоков без синхронизации. (Если они пишут по одному и тому же адресу, это будет https://en.wikipedia.org/wiki/Race_condition, и это сделает программу непредсказуемой.)

В вашем коде есть массив B, который разделяется и изменяется обоими потоками. Этот одновременный доступ неверен. Попробуйте использовать локальный массив (определите его внутри параллельного для цикла { ... } цикла, некоторые документы ) и проверьте другие переменные для доступа на запись из обоих потоков.

...