我看到的问题是,如果您想像这样分配迭代:
0123...3210(编号为线程,位置为迭代)
您必须修改循环,因为我看到如果您不跟踪 N-i-1 迭代,您将无法做到这一点,因此代码将如下所示:
#pragma omp parallel for private (i, j, k) reduction(+:x)
for (i=0; i<N/2; i++)
{
k = N-1-i;
printf ("\n i = %d ", i);
printf ("\n k = %d\n", k);
C[i] = 0;
C[k] = 0;
for (j=0; j<N; j++)
{
C[i] += MAT[i][j] * B[j];
C[k] += MAT[k][j] * B[j];
}
x += C[i];
x += C[k];
}
所以同一个线程将执行 0 和 N,下一个线程 1 和 N-1...您甚至可以在每个循环的更多执行中分配迭代,但请记住,分配的数量应该是
如果你想保持顺序:0 N, 1 N-1...你必须使用子句ordered和ordered块但这对并行化没有意义,因为不同的线程并发执行直到它们遇到ordered区域,然后他们以与在串行版本中执行的顺序相同的顺序顺序执行这部分,但增加了线程之间同步的重载时间,您将以较慢的串行版本结束。
#pragma omp parallel for ordered private (i, j, k) reduction(+:x)
for (i=0; i<N/2; i++)
{
#pragma omp ordered
k = N-1-i;
printf ("\n i = %d ", i);
printf ("\n k = %d\n", k);
C[i] = 0;
C[k] = 0;
for (j=0; j<N; j++)
{
C[i] += MAT[i][j] * B[j];
C[k] += MAT[k][j] * B[j];
}
x += C[i];
x += C[k];
}
我认为 N 总是由于您要进行的分配类型,但如果不是这种情况,您可以在 for 之后添加它以执行术语的操作在中间,因为虽然我没有尝试过,但我认为这个 if 顺序它会比并行 for 中消耗的时间更少,因为它是要处理的最后一个元素而且您似乎不想并行化内部循环。
if(N%2 != 0)
{
i = N/2;
C[i] = 0;
for (j=0; j<N; j++)
{
C[i] += MAT[i][j] * B[j];
}
x += C[i];
}