我是OpenMP的新手,刚刚完成了我的第一次尝试,它是矩阵乘法。我只是想知道openMP中是否存在默认的块分隔符?以下是我的代码:
#include <stdio.h>
#include <omp.h>
#define MAX_THREADS 4
#define ASIZE 500
int main()
{
/*intialization of 2 matrix*/
long matrixa [ASIZE][ASIZE];
long matrixb [ASIZE][ASIZE];
long matrixc [ASIZE][ASIZE] = {0};
for(int i=0; i<ASIZE; i++)
for(int j=0;j<ASIZE; j++)
{
matrixa [i][j] = 1;
matrixb [i][j] = j;
}
omp_set_num_threads(MAX_THREADS);
#pragma omp parallel
{
long cprivate [ASIZE][ASIZE] = {0};
#pragma omp for
for(int i =0 ;i<ASIZE; i++)
for(int j=0; j<ASIZE; j++)
for(int k=0; k<ASIZE; k++)
cprivate[i][j]+=matrixa[i][k]*matrixb[k][j];
#pragma omp critical
for(int i =0 ;i<ASIZE; i++)
for(int j=0; j<ASIZE; j++)
matrixc[i][j]+=cprivate[i][j];
//#pragma omp barrier
if(omp_get_thread_num() ==0)
for(int i=0; i<50; i++)
printf("Snap of C array %lu n", matrixc[1][i]); //print out chunk of the first row!
}
}
我想这样做是因为无论我是否添加#pragma omp barrier
,我都可以得到预期的结果,应该是#pragma omp critical
块完全执行后的结果。
问题
@为什么有没有#pragma omp barrier
没有区别?
@我还注意到,一旦我将数组大小增加到600,它在执行.o文件时会提醒分段错误,我最初猜测它来自int范围(我已将数组类型从int[]修改为long[]),没有区别。
您的代码可能会失败,因为您使用的是自动存储。您应该使用动态或静态存储。以下是使用静态存储修复代码的方法
#include <stdio.h>
#include <stdlib.h>
#define ASIZE 1000
long matrixa [ASIZE][ASIZE];
long matrixb [ASIZE][ASIZE];
long matrixc [ASIZE][ASIZE]; //set to zero by default with static storage
int main() {
for(int i=0; i<ASIZE; i++) {
for(int j=0;j<ASIZE; j++) {
matrixa [i][j] = 1;
matrixb [i][j] = j;
}
}
#pragma omp parallel for
for(int i=0 ;i<ASIZE; i++) {
for(int j=0; j<ASIZE; j++) {
long sum = 0;
for(int k=0; k<ASIZE; k++) {
sum += matrixa[i][k]*matrixb[k][j];
}
matrixc[i][j] = sum;
}
}
for(int i=0; i<50; i++) printf("Snap of C array %lu n", matrixc[1][i]);
}
如果您想要为每个线程静态分配缓冲区,则需要使用threadprivate
,否则使用动态分配。
不需要使用屏障的原因是critical
和许多其他构造隐含了屏障。为了消除隐性障碍,在某些情况下可以使用nowait
(例如#pragma omp parallel for nowait
)。