rel*_*lot 2 c c++ parallel-processing openmp
openmp的这两种实现之间有区别吗?
float dot_prod (float* a, float* b, int N)
{
float sum = 0.0;
#pragma omp parallel for shared(sum)
for (int i = 0; i < N; i++) {
#pragma omp critical
sum += a[i] * b[i];
}
return sum;
}
Run Code Online (Sandbox Code Playgroud)
和相同的代码但第 4 行没有 shared(sum) 因为 sum 已经初始化?
#pragma omp parallel for
for(int = 0; ....)
Run Code Online (Sandbox Code Playgroud)
openmp 中 private 的相同问题:
是
void work(float* c, int N)
{
float x, y; int i;
#pragma omp parallel for private(x,y)
for (i = 0; i < N; i++)
{
x = a[i]; y = b[i];
c[i] = x + y;
}
}
Run Code Online (Sandbox Code Playgroud)
与没有 private(x,y) 一样,因为 x 和 y 没有初始化?
#pragma omp parallel for
Run Code Online (Sandbox Code Playgroud)
openmp的这两种实现之间有区别吗?
float dot_prod (float* a, float* b, int N)
{
float sum = 0.0;
# pragma omp parallel for shared(sum)
for (int i = 0; i < N; i++) {
#pragma omp critical
sum += a[i] * b[i];
}
return sum;
}
Run Code Online (Sandbox Code Playgroud)
在 openMP 中,在并行范围之外声明的变量是shared,除非它被显式呈现private。因此shared可以省略声明。
但是您的代码远非最佳。它可以工作,但比它的顺序对应物要慢得多,因为critical将强制顺序处理和创建临界区具有重要的时间成本。
正确的实现将使用reduction.
float dot_prod (float* a, float* b, int N)
{
float sum = 0.0;
# pragma omp parallel for reduction(+:sum)
for (int i = 0; i < N; i++) {
sum += a[i] * b[i];
}
return sum;
}
Run Code Online (Sandbox Code Playgroud)
减少创建一个隐藏的局部变量,以在每个线程中并行累积,并在线程销毁之前对共享变量执行这些局部总和的原子加法sum。
openmp 中 private 的相同问题:
void work(float* c, int N)
{
float x, y; int i;
# pragma omp parallel for private(x,y)
for (i = 0; i < N; i++)
{
x = a[i]; y = b[i];
c[i] = x + y;
}
}
Run Code Online (Sandbox Code Playgroud)
默认情况下,x和y是共享的。因此,没有 private行为会有所不同(并且有问题,因为所有线程都将修改相同的全局可访问变量x并且y没有原子访问)。
与没有 private(x,y) 一样,因为 x 和 y 没有初始化?
初始化x并y不要紧,最重要的是它们声明的位置。为了确保正确的行为,它们必须是私有的,并且代码将是正确的,x并且y在循环中使用之前设置。