我的代码旨在将两个数组组合成第三个数组,并多次执行此操作。我希望使用OpenMP的方式将其并行化,但结果并不是我所期望的。也就是说,第一个检查已经在a[0]!=0处中断。
MWE是:
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
int main(int argc, char *argv[])
{
int i = 0;
int j = 0;
long length = 10000;
long nSamples = 1000;
double *a, *b, *c;
double start = 0;
double end = 0;
int nthreads = 0;
// Array Allocation and Initialisation
a = (double *)malloc(length * sizeof(double));
b = (double *)malloc(length * sizeof(double));
c = (double *)malloc(length * sizeof(double));
for (i = 0; i < length; i++)
{
a[i] = 0.0;
b[i] = 0.0;
c[i] = 0.0;
}
// Get the maximum number of threads and evaluate the number of threads per group
#pragma omp parallel shared(nthreads)
{
nthreads = omp_get_num_threads() / 2;
}
#pragma omp parallel for shared(nthreads, a, b, c) num_threads(nthreads) collapse(2)
for (i = 0; i < nSamples; i++)
{
for (j = 0; j < length; j++)
{
a[j] = a[j] + 2.0;
b[j] = b[j] + 2.0;
c[j] = a[j] + b[j];
}
}
/*Check correctness*/
for (i = 0; i < length; i++)
{
if (a[i] != 2.0 * nSamples)
{
printf("a not equal at %d\n", i);
break;
}
if (b[i] != 2.0 * nSamples)
{
printf("b ot equal at %d\n", i);
break;
}
if (c[i] != 4.0 * nSamples)
{
printf("c ot equal at %d\n", i);
break;
}
}
free(a);
free(b);
free(c);
return 0;
}
如果我只并行化内部循环,检查就能正常工作。为了实现这一点,我用途:
for (i = 0; i < nSamples; i++)
{
#pragma omp parallel for private(j) shared(a, b, c) num_threads(nthreads)
for (j = 0; j < length; j++)
{
a[j] = a[j] + 2.0;
b[j] = b[j] + 2.0;
c[j] = a[j] + b[j];
}
}
我知道openMP将循环的每次迭代视为独立于其他迭代。我假设这会导致线程1上的迭代i=5写入另一个线程的迭代i=9的a[j],从而导致差异。这是正确的吗?使用openMP的方法可以避免这种情况吗?
1条答案
按热度按时间qvtsj1bj1#
因此,问题在于OpenMP将循环的每次迭代视为独立于其他迭代,除非您告诉它减少结果并相应地收集步骤。在上面的示例中,可以通过在外部for循环前面使用以下表达式来实现这一点: