оптимизация openmp с условием возврата

#c #c #multithreading #parallel-processing #openmp

#c #c #многопоточность #параллельная обработка #openmp

Вопрос:

Я новичок в параллельном программировании OpenMP, и мне трудно оптимизировать мою функцию, которая должна возвращать -1 в случае, если столбец пуст.

Вот моя функция. Исходная матрица имеет некоторые значения и norm_matrix строится как диагональная матрица, где каждый столбец содержит максимальное значение из соответствующего столбца исходной матрицы.

Я выполняю это для матрицы размером 1000, например, если моя исходная матрица

  3   2   3   3
 2   4   5   5
 1   4  91   8
32  12   9  63 
 

тогда вычисленное norm_matrix значение будет

 32   0   0   0
 0  12   0   0 
 0   0  91   0 
 0   0   0  63 
 

Если какой-либо столбец содержит все нули, то функция должна возвращать значение -1.

Вот моя функция, которую я пытаюсь оптимизировать в OpenMP:

 int statistic_norm_matrix(double* source_matrix, double* norm_matrix, int size) {
   int col, row;

   for (col = 0; col < size; col  ) {
      norm_matrix[col * size   col] = source_matrix[col];

      for (row = 0; row < size; row  ) {
         norm_matrix[col * size   col] = fmax(norm_matrix[col * size   col], source_matrix[row * size   col]);
      }

      if (norm_matrix[col * size   col] == 0) {
         printf("can't process a matrix where the max col value is 0");
         return -1;
      }

      norm_matrix[col * size   col] = (1 / norm_matrix[col * size   col]);

      if (col == size - 1) {
         print_matrix("matrix-norm", norm_matrix, size);
      }
   }
   return 0; 
 

Это попытка распараллеливания с OpenMP, но я не вижу разницы в производительности:

 int statistic_norm_matrix(double* source_matrix, double* norm_matrix, int size) {
   int col, row;
    int flag=0;
   
        #pragma omp parallel for shared(source_matrix,norm_matrix) private(col,row) 
        for (col = 0; col < size; col  ) {
            norm_matrix[col * size   col] = source_matrix[col];

                for (row = 0; row < size; row  ) {
                    norm_matrix[col * size   col] = fmax(norm_matrix[col * size   col], source_matrix[row * size   col]);
                }
        
                if (norm_matrix[col * size   col] == 0) {
                    printf("can't process a matrix where the max col value is 0");
                    flag=-1;
                }

                norm_matrix[col * size   col] = (1 / norm_matrix[col * size   col]);

            }

        print_matrix("matrix-norm", norm_matrix, size);
        return flag;
}
 

Комментарии:

1. Приятно знать, что Bosch — удивительная компания 🙂

Ответ №1:

Когда norm_matrix[col * size col] == 0 вы получите ошибку деления на ноль в инструкции (1 / norm_matrix[col * size col]); . Предполагая, что когда flag = -1 вы должны полностью выйти из параллельной области, вам следует использовать #pragma omp cancel для

 int statistic_norm_matrix(double* source_matrix, double* norm_matrix, int size) {
        int flag = 0;   
        #pragma omp parallel for shared(source_matrix,norm_matrix)
        for (int col = 0; col < size; col  ) {
             norm_matrix[col * size   col] = source_matrix[col];
             for (int row = 0; row < size; row  ) {
                 norm_matrix[col * size   col] = fmax(norm_matrix[col * size   col], source_matrix[row * size   col]);
             }
             if (norm_matrix[col * size   col] == 0) {
                    flag = -1;
                    #pragma omp cancel for
             }

             norm_matrix[col * size   col] = (1 / norm_matrix[col * size   col]);
        }

     print_matrix("matrix-norm", norm_matrix, size);
     return flag;
}
 

Я провел быстрый тест на своей машине (т. Е. С 4 ядрами), измеряя время statistic_norm_matrix одного, без подсчета print_matrix , и для матрицы 1000x1000 :

1 Поток: затраченное время составляет 0,010852 (с)

Время, затрачиваемое на 2 потока, составляет 0,005325 (с)

Время, затрачиваемое на 4 потока, составляет 0,002891 (с)

для матрицы 10000x10000 :

Время, затрачиваемое на 1 поток, составляет 1.937415 (с)

Время, затрачиваемое на 2 потока, составляет 1.052908 (с)

Время, затрачиваемое на 4 потока, составляет 0,807185 (с)

Тесты с 1 потоком были выполнены без каких-либо openmp директив. Таким образом, либо что-то не так с способом компиляции / запуска, и ваш код фактически не выполняется параллельно, либо что-то не так с тем, как вы измеряете время.

Комментарии:

1. Отмена была введена еще в OpenMP 4.0. Старые компиляторы должны ее поддерживать.