如何openmp并行化递增两个变量的循环

时间:2019-02-26 20:53:41

标签: openmp

作为OpenMP的第一步,我为自己挑战了一些矩阵分解算法的并行化。我选择了可​​旋转的Crout,可在此处找到源: http://www.mymathlib.com/c_source/matrices/linearsystems/crout_pivot.c

在该分解函数的底部,有一个外部for循环,该循环同时遍历i和p_row。当然,OpenMP与我一样困惑,拒绝对此做任何事情。

我全神贯注于它之后,我认为我已经将其分解为可读的形式:

ProductID   Year
-----------------
1           2010
1           2011
1           2012
......

在这一点上,串行运行仍然具有与原始代码相同的结果。 然后添加一些编译指示,如下所示:

p_row = p_k + n;
for (i = k+1; i < n; i++) {
    for (j = k+1; j < n; j++) *(p_row + j) -= *(p_row + k) * *(p_k + j);
    p_row += n;
}

结果基本上是随机的。

我想念什么?

1 个答案:

答案 0 :(得分:0)

我尚未测试过您对原始代码的适应性,但是您的程序有几个问题。

#pragma omp parallel for private (i,j) shared (n,k,p_row,p_k)
默认行为是在范围之外共享声明的var,因此共享声明是无用的。 但是这些var应该共享并设为私有。
n在迭代过程中保持不变,因此最好有一个本地副本
k和p_k的同上
p_row已修改,但您确实要复制p_row。这将确保适当的并行处理,以便每个线程处理不同的行。问题是要在不同线程中计算p_row值。

在外循环中,迭代0将使用p_row,第二个迭代p_row + n,迭代l p_row + l * n。您的迭代将分布在多个线程上。假设每个线程处理m次迭代。线程0将处理i = k + 1到i = m +(k + 1)和p_row到p_row + m * n,线程1 i = m + 1 +(k + 1)到i = 2m +(k + 1)和p_row + n *(m + 1)到p_row + 2 * m * n,依此类推。因此,您可以使用i的值计算循环开始时应具有p_row的值。 这是一个可能的实现方式

p_row = p_k + n;
#pragma omp parallel for private(i,j) firstprivate(n, k, p_row, p_k)
// first private insures initial values are kept
{ 
  for (i = k+1, p_row=p_row+(i-(k+1))*n; i < n; i++, p_row += n) {
    for (j = k+1; j < n; j++) 
       *(p_row + j) -= *(p_row + k) * *(p_k + j);
}

p_row增量位于for循环中。这应该在顺序环境中继续工作。

批评是没有用的(并且在您先前的代码中有错误)。刷新是在并行部分的末尾隐含的(编译指示只是“ omp刷新”)。