c - 如何制作这两个循环的并行静态和动态版本?
问题描述
我想知道在执行此代码的并行版本时如何获得相同的结果:
#include <stdlib.h>
#include <stdio.h>
#include <omp.h>
#define N 10000
int MAT[N][N], B[N], C[N];
void main ()
{
int i, j, x = 0;
for (i=0; i<N; i++)
{
B[i] = i % 3;
for (j=0; j<N; j++) MAT[i][j] = (i + j) % 7 - 2;
}
#pragma omp parallel for schedule(static,1)
for (i=0; i<N; i++) {
C[i] = 0;
#pragma omp parallel for schedule(static,1)
for (j=0; j<N; j++)
C[i] += MAT[i][j] * B[j];
x += C[i];
}
printf ("\n x = %d\n", x);
}
结果必须是 99990002,但我使用 2、4、8、16 和 32 个线程获得了不同的结果。而且我必须使用具有所有不同线程数的静态和动态并行版本获得相同的结果。
解决方案
最简单的解决方案是仅并行化外循环:
#include <stdlib.h>
#include <stdio.h>
#include <omp.h>
#define N 10000
int MAT[N][N], B[N];
void main ()
{
int i, j, x = 0;
for (i=0; i<N; i++){
B[i] = i % 3;
for (j=0; j<N; j++)
MAT[i][j] = (i + j) % 7 - 2;
}
#pragma omp parallel for schedule(static, 1) reduction(+:x)
for (i=0; i<N; i++)
for (j=0; j<N; j++)
x += MAT[i][j] * B[j];
printf ("\n x = %d\n", x);
}
动态版本如下:
#pragma omp parallel for schedule(dynamic, 1) reduction(+:x)
for (i=0; i<N; i++)
for (j=0; j<N; j++)
x += MAT[i][j] * B[j];
printf ("\n x = %d\n", x);
除此之外,您的代码还存在以下问题:
#pragma omp parallel for schedule(static,1)
for (i=0; i<N; i++) {
C[i] = 0;
#pragma omp parallel for schedule(static,1)
您的内部循环实际上并没有像您希望的那样在线程之间分配迭代。因为您parallel
再次添加了该子句,并假设您已禁用嵌套并行性,默认情况下,在外部创建的每个线程parallel region
都将“按顺序”执行该区域内的代码,即:
#pragma omp parallel for schedule(static,1)
for (j=0; j<N; j++)
C[i] += MAT[i][j] * B[j];
x += C[i];
}
另一个问题是你在更新变量的过程中存在竞争条件x
,这可以通过在( ie, ) 中添加 OpenMPreduction
子句来解决。最后,由于现在我们减少了变量,因此数组不再存在。parallel for
#pragma omp parallel for schedule(static, 1) reduction(+:x)
x
C
如果你真的想同时并行化两个循环,你需要使用 OpenMPcollapse
子句,并相应地调整你的代码,例如:
#include <stdlib.h>
#include <stdio.h>
#include <omp.h>
#define N 10000
int MAT[N][N], B[N];
void main ()
{
int i, j, x = 0;
for (i=0; i<N; i++){
B[i] = i % 3;
for (j=0; j<N; j++)
MAT[i][j] = (i + j) % 7 - 2;
}
#pragma omp parallel for schedule(static, 1) collapse(2) reduction(+:x)
for (i=0; i<N; i++)
for (j=0; j<N; j++)
x += MAT[i][j] * B[j];
printf ("\n x = %d\n", x);
}
推荐阅读
- javascript - 在 javascript 中为数组和对象使用 variable.length 时需要注意什么?
- javascript - React Native:从函数渲染文本
- javascript - 计算滚动时窗口的高度
- android - 如何使用底部导航栏将地图视图设置为全屏
- javascript - 带有 ng-if 的模板字符串有错误:$parse:syntax
- .net - 点网框架与点网核心 sdk
- rest - 按主机名过滤在我的 WireShark 中不起作用
- sql - 如何在 SQL 中查找两个日期时间行的时间平均值?
- objective-c - 如何将 Win32 FILETIME 转换为 NSDate
- reactjs - 如何在 reactjs 的新选项卡/窗口中打开表单