如何为每个线程分配一个特定的作业,以便在openmp中添加矩阵

时间:2015-03-24 15:24:53

标签: c multithreading parallel-processing openmp

我正在尝试创建一个矩阵添加程序来练习OpenMP。我有N ^ 2个处理器/线程,需要分配每个线程,以便计算结果矩阵的一个条目。例如,如果我有两个大小为NxN的矩阵A和B,那么每个线程应该计算得到的矩阵C的一个条目。在读取OpenMp中的一些初学者教程时,似乎#pragma omp parallel for directive将任务分开同样在指定的线程总数中。但是在下面的代码中只有3个线程是活动的,而不是我想要的9个线程。

我的代码如下:

 #include <stdio.h>
#include "omp.h"



void  main() {

  // omp_set_num_threads(NUM_THREADS);
  int i, k;
  int N=3;

  int A[3][3] = { {1, 2, 3},{ 5, 6, 7}, {8,9,10} };
  int B[3][3] =  { {1, 2, 3},{ 5, 6, 7}, {8,9,10} };
  int C[3][3] ;

  omp_set_dynamic(0);
   omp_set_num_threads(9);
   // printf("Num of threads %i \n", omp_get_max_threads());

#pragma omp parallel for private(i,k) shared(A, B, C, N)

  for (i = 0; i< N; i++) {
    for (k=0; k< N;k++){

           int j = omp_get_thread_num();

       C[i][k] = A[i][k] +  B[i][k] ;


              printf("I m thread %d computing A[%d][%d] and B[%d][%d] = %d \n ", j, i,k, i,k, C[i][k]);

  }
  }


  int n, m;
  for (n=0; n<3; n++) {
    for ( m=0;m<3;m++){
      printf("C[%d][%d] = %d \n",n,m, C[n][m]);   

 }


}

}

我得到的输出是:

I m thread 0 computing A[0][0] and B[0][0] = 2 
 I m thread 1 computing A[1][0] and B[1][0] = 10 
 I m thread 1 computing A[1][1] and B[1][1] = 12 
 I m thread 1 computing A[1][2] and B[1][2] = 14 
 I m thread 0 computing A[0][1] and B[0][1] = 4 
 I m thread 0 computing A[0][2] and B[0][2] = 6 
 I m thread 2 computing A[2][0] and B[2][0] = 16 
 I m thread 2 computing A[2][1] and B[2][1] = 18 
 I m thread 2 computing A[2][2] and B[2][2] = 20 
 C[0][0] = 2 
C[0][1] = 4 
C[0][2] = 6 
C[1][0] = 10 
C[1][1] = 12 
C[1][2] = 14 
C[2][0] = 16 
C[2][1] = 18 
C[2][2] = 20 

我想要的是九个线程中的每一个都计算矩阵C的一个条目。任何人都可以帮忙解决这个问题。我是C和OpenMP的新手。我也对private子句中私有变量的确切功能感到困惑。例如,如果我将'i'和'k'指定为私有,那么这是否意味着每个线程都有一个'i'和'k'的副本,因此可能会运行它们自己的循环迭代?但这没有意义,因为在上面的输出线程0中计算所有第0行值,而线程1计算所有第1行值。如果没有任何具体指令,这是如何发生的呢?谢谢你的帮助!

2 个答案:

答案 0 :(得分:3)

在外部for循环上使用#pragma omp parallel for,它仅应用于外部循环,它只迭代3次(N = 3),因此您只需要3个线程。

如果你想使用9个线程,你应该使用单个索引将2d数组折叠为1d,我们称之为p

#pragma omp parallel for private(i, k, p) shared(A, B, C, N)
for (p = 0; p < N * N; p++) {
    i = p / N;
    k = p % N;
    C[i][k] = A[i][k] + B[i][k];
}

正如George的回答和Timothy的评论所述,您也可以使用OpenMP的collapse(2)关键字来实现同样的目标。

答案 1 :(得分:3)

另一种方式,如果你想保留2个循环,除了'chrk'的回答,就是使用:

#pragma omp parallel for private(i,k) shared(A, B, C, N) collapse(2)

像这样,你将在两个循环中并行执行。 因为,现在,您只在外部循环中执行并行执行。 这就是为什么你看到例如线程1计算所有第1行值的原因。