在OpenMP中为每个内部循环启动一个线程

我是OpenMP的新手,我正在尝试启动一个单独的线程来处理2D数组中的每个项目。

基本上,这个:

for (i = 0; i < dimension; i++) { for (int j = 0; j < dimension; j++) { a[i][j] = b[i][j] + c[i][j]; 

我正在做的是这样的:

 #pragma omp parallel for shared(a,b,c) private(i,j) reduction(+:diff) schedule(dynamic) for (i = 0; i < dimension; i++) { for (int j = 0; j < dimension; j++) { a[i][j] = b[i][j] + c[i][j]; 

这实际上是为每个2D项启动一个线程还是没有? 我该怎么测试? 如果是错的,那么正确的方法是什么? 谢谢!

注意:代码已经大大简化了

在代码示例中只有外部循环是并行的。 您可以通过在内部循环中打印omp_get_thread_num()来进行测试,您将看到,对于给定的i ,线程数是相同的(当然,此测试是示范性的而不是确定性的,因为不同的运行将给出不同的结果)。 例如,用:

 #include  #include  #define dimension 4 int main() { #pragma omp parallel for for (int i = 0; i < dimension; i++) for (int j = 0; j < dimension; j++) printf("i=%d, j=%d, thread = %d\n", i, j, omp_get_thread_num()); } 

我明白了:

 i=1, j=0, thread = 1 i=3, j=0, thread = 3 i=2, j=0, thread = 2 i=0, j=0, thread = 0 i=1, j=1, thread = 1 i=3, j=1, thread = 3 i=2, j=1, thread = 2 i=0, j=1, thread = 0 i=1, j=2, thread = 1 i=3, j=2, thread = 3 i=2, j=2, thread = 2 i=0, j=2, thread = 0 i=1, j=3, thread = 1 i=3, j=3, thread = 3 i=2, j=3, thread = 2 i=0, j=3, thread = 0 

至于你的其余代码,你可能想要在一个新问题中加入更多细节(很难从小样本中得知),但是例如,当j仅在稍后声明时,你不能放private(j) 。 在我上面的例子中,它是自动私有的。 我猜diff是一个我们在样本中看不到的变量。 此外,循环变量i是自动私有的(从版本2.5规范 - 3.0规范中相同)

for构造中for或parallel的for循环中的循环迭代变量在该构造中是私有的。

编辑:以上所有内容对于您和我显示的代码都是正确的,但您可能对以下内容感兴趣。 对于OpenMP 3.0版(在例如gcc版本4.4中提供 ,但不是版本4.3),有一个collapse子句,您可以在其中编写代码,但使用#pragma omp parallel for collapse (2)以并行化两个for循环(请参阅规范 )。

编辑 :好的,我下载了gcc 4.5.0并运行了上面的代码,但使用collapse (2)得到以下输出,显示内部循环现在并行化:

 i=0, j=0, thread = 0 i=0, j=2, thread = 1 i=1, j=0, thread = 2 i=2, j=0, thread = 4 i=0, j=1, thread = 0 i=1, j=2, thread = 3 i=3, j=0, thread = 6 i=2, j=2, thread = 5 i=3, j=2, thread = 7 i=0, j=3, thread = 1 i=1, j=1, thread = 2 i=2, j=1, thread = 4 i=1, j=3, thread = 3 i=3, j=1, thread = 6 i=2, j=3, thread = 5 i=3, j=3, thread = 7 

如果要并行化两个循环, 这里的注释(搜索“Workarounds”)也与版本2.5中的变通方法相关,但上面引用的2.5版规范非常明确(参见A.35节中的不符合示例) 。

您可以尝试使用嵌套的omp并行fors(在omp_set_nested(1)调用之后),但是在所有openmp实现上都不支持它们。

所以我想做一些2D网格并从单一开始网格上的所有线程(例如固定的4×4线程网格):

 #pragma omp parallel for for(k = 0; k < 16; k++) { int i,j,i_min,j_min,i_max,j_max; i_min=(k/4) * (dimension/4); i_max=(k/4 + 1) * (dimension/4); j_min=(k%4) * (dimension/4); j_max=(k%4 + 1) * (dimension/4); for(i=i_min;i