如何在openmp中为每个线程分配特定的作业以进行矩阵加法
How to assign a specific job to each thread for matrix addition in openmp
我正在尝试创建一个矩阵加法程序来练习 OpenMP。我有 N^2 processors/threads 并且需要分配每个线程,以便它计算结果矩阵的一个条目。例如,如果我有两个大小为 NxN 的矩阵 A 和 B,那么每个线程都应该计算结果矩阵 C 的一个条目。在阅读 OpenMp 中的一些初学者教程后,#pragma omp parallel for 指令似乎划分了任务在指定的线程总数中均等。但是在下面的代码中只有 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 的新手。我也对私有子句中私有变量的确切功能感到困惑。例如,如果我将 'i' 和 'k' 指定为私有,那么这是否意味着每个线程都将具有 'i' 和 'k' 的副本,因此可能 运行自己迭代循环?但这没有意义,因为在上面的输出中,线程 0 正在计算所有第 0 行的值,而线程 1 计算所有第 1 行的值。在没有任何特定指令的情况下,这是如何自行发生的?感谢您的帮助!
使用#pragma omp parallel for
on outer for loop,它只应用于外层循环,它只迭代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)
关键字来实现相同的目的。
另一种方法,如果你想保留 2 个循环,除了 'chrk' 答案,就是使用:
#pragma omp parallel for private(i,k) shared(A, B, C, N) collapse(2)
像这样,您将在两个循环中并行执行。
因为,现在,您只能在外循环中并行执行。
这就是为什么您看到线程 1 计算所有行 1 值的原因。
我正在尝试创建一个矩阵加法程序来练习 OpenMP。我有 N^2 processors/threads 并且需要分配每个线程,以便它计算结果矩阵的一个条目。例如,如果我有两个大小为 NxN 的矩阵 A 和 B,那么每个线程都应该计算结果矩阵 C 的一个条目。在阅读 OpenMp 中的一些初学者教程后,#pragma omp parallel for 指令似乎划分了任务在指定的线程总数中均等。但是在下面的代码中只有 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 的新手。我也对私有子句中私有变量的确切功能感到困惑。例如,如果我将 'i' 和 'k' 指定为私有,那么这是否意味着每个线程都将具有 'i' 和 'k' 的副本,因此可能 运行自己迭代循环?但这没有意义,因为在上面的输出中,线程 0 正在计算所有第 0 行的值,而线程 1 计算所有第 1 行的值。在没有任何特定指令的情况下,这是如何自行发生的?感谢您的帮助!
使用#pragma omp parallel for
on outer for loop,它只应用于外层循环,它只迭代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)
关键字来实现相同的目的。
另一种方法,如果你想保留 2 个循环,除了 'chrk' 答案,就是使用:
#pragma omp parallel for private(i,k) shared(A, B, C, N) collapse(2)
像这样,您将在两个循环中并行执行。 因为,现在,您只能在外循环中并行执行。 这就是为什么您看到线程 1 计算所有行 1 值的原因。