首页 > 解决方案 > 如何制作这两个循环的并行静态和动态版本?

问题描述

我想知道在执行此代码的并行版本时如何获得相同的结果:

#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 个线程获得了不同的结果。而且我必须使用具有所有不同线程数的静态和动态并行版本获得相同的结果。

标签: cmultithreadingfor-loopparallel-processingopenmp

解决方案


最简单的解决方案是仅并行化外循环:

#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)xC

如果你真的想同时并行化两个循环,你需要使用 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);
}

推荐阅读