作为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;
}
结果基本上是随机的。
我想念什么?
答案 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刷新”)。