首页 > 解决方案 > 带返回条件的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;
}

标签: c++cmultithreadingparallel-processingopenmp

解决方案


norm_matrix[col * size + col] == 0您在语句上得到除以零错误时(1 / norm_matrix[col * size + col]);。假设当flag = -1您应该完全退出并行区域时,您应该使用 #pragma omp cancel for

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 (s)

2 线程时间为 0.005325 (s)

4 线程时间为 0.002891 (s)

对于矩阵10000x10000

1 线程时间为 1.937415 (s)

2 线程时间为 1.052908 (s)

4 线程时间为 0.807185 (s)

1 个线程的测试是在没有任何openmp指令的情况下完成的。所以要么编译/运行的方式有问题,你的代码实际上没有并行运行,要么你测量时间的方式有问题。


推荐阅读