繁体   English   中英

OpenMP并行代码变慢

[英]OpenMP parallel code slower

我有两个要并行化的循环

#pragma omp parallel for
  for (i = 0; i < ni; i++)
    for (j = 0; j < nj; j++) {
      C[i][j] = 0;
      for (k = 0; k < nk; ++k)
        C[i][j] += A[i][k] * B[k][j];
    }
#pragma omp parallel for
  for (i = 0; i < ni; i++)
    for (j = 0; j < nl; j++) {
      E[i][j] = 0;
      for (k = 0; k < nj; ++k)
        E[i][j] += C[i][k] * D[k][j];
    }

奇怪的是,即使使用大量线程,顺序执行也比并行版本要快得多。 难道我做错了什么? 请注意,所有数组都是全局的。 这有什么区别吗?

并行外部循环的迭代共享其内部循环的索引变量( jk )。 这肯定会使您的代码比您预期的要慢一些,即,您的循环不会“尴尬” (或“令人愉快”)并行和并行循环迭代需要以某种方式从共享内存访问这些变量。

更糟糕的是,因此,您的代码包含竞争条件 结果,它将无法确定地运行。 换句话说:您的并行矩阵乘法实现现在不正确! (继续检查计算结果。))

您要做的是确保外部循环的所有迭代都具有索引变量jk的专用副本。 您可以通过在并行循环范围内声明以下变量来实现此目的:

int i;

#pragma omp parallel for
  for (i = 0; i < ni; i++) {
    int j1, k1;  /* explicit local copies */
    for (j1 = 0; j1 < nj; j1++) {
      C[i][j1] = 0;
      for (k1 = 0; k1 < nk; ++k1)
        C[i][j1] += A[i][k1] * B[k1][j1];
    }
  }        
#pragma omp parallel for
  for (i = 0; i < ni; i++) {
    int j2, k2;  /* explicit local copies */
    for (j2 = 0; j2 < nl; j2++) {
      E[i][j2] = 0;
      for (k2 = 0; k2 < nj; ++k2)
        E[i][j2] += C[i][k2] * D[k2][j2];
    }
  }

或在循环编译中将它们声明为private

int i, j, k;

#pragma omp parallel for private(j, k)
  for (i = 0; i < ni; i++)
    for (j = 0; j < nj; j++) {
      C[i][j] = 0;
      for (k = 0; k < nk; ++k)
        C[i][j] += A[i][k] * B[k][j];
    }
#pragma omp parallel for private(j, k)
  for (i = 0; i < ni; i++)
    for (j = 0; j < nl; j++) {
      E[i][j] = 0;
      for (k = 0; k < nj; ++k)
        E[i][j] += C[i][k] * D[k][j];
    }

这些更改会使并行实现比顺序实现更快吗? 很难说。 这取决于您的问题大小。 并行化(特别是通过OpenMP进行并行化)会带来一些开销。 仅当产生足够的并行工作时,在并行线程上分配工作的收益才会超过产生的间接费用。

为了找出足以满足您的代码和软件/硬件平台需求的工作量,建议您以不同的矩阵大小运行代码以进行实验。 然后,如果您还期望矩阵尺寸太小而无法作为计算的输入,则可能需要使并行处理成为条件处理(例如,使用if -clauses修饰循环编译):

#pragma omp parallel for private (j, k) if(ni * nj * nk > THRESHOLD)
  for (i = 0; i < ni; i++) {
     ...
  }
#pragma omp parallel for private (j, k) if(ni * nl * nj > THRESHOLD)
  for (i = 0; i < ni; i++) {
    ...
  }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM