【发布时间】:2018-07-01 03:30:20
【问题描述】:
我使用 OpenMP 和 AVX2 编写了 Matrix-Vector 产品程序。
但是,由于 OpenMP,我得到了错误的答案。 真正的答案是数组 c 的所有值都会变成 100。
我的答案是 98、99 和 100 的混合。
实际代码如下。
我用 -fopenmp、-mavx、-mfma 编译了 Clang。
#include "stdio.h"
#include "math.h"
#include "stdlib.h"
#include "omp.h"
#include "x86intrin.h"
void mv(double *a,double *b,double *c, int m, int n, int l)
{
int k;
#pragma omp parallel
{
__m256d va,vb,vc;
int i;
#pragma omp for private(i, va, vb, vc) schedule(static)
for (k = 0; k < l; k++) {
vb = _mm256_broadcast_sd(&b[k]);
for (i = 0; i < m; i+=4) {
va = _mm256_loadu_pd(&a[m*k+i]);
vc = _mm256_loadu_pd(&c[i]);
vc = _mm256_fmadd_pd(vc, va, vb);
_mm256_storeu_pd( &c[i], vc );
}
}
}
}
int main(int argc, char* argv[]) {
// set variables
int m;
double* a;
double* b;
double* c;
int i;
m=100;
// main program
// set vector or matrix
a=(double *)malloc(sizeof(double) * m*m);
b=(double *)malloc(sizeof(double) * m*1);
c=(double *)malloc(sizeof(double) * m*1);
//preset
for (i=0;i<m;i++) {
a[i]=1;
b[i]=1;
c[i]=0.0;
}
for (i=m;i<m*m;i++) {
a[i]=1;
}
mv(a, b, c, m, 1, m);
for (i=0;i<m;i++) {
printf("%e\n", c[i]);
}
free(a);
free(b);
free(c);
return 0;
}
我知道关键部分会有所帮助。但是临界区很慢。
那么,我该如何解决这个问题呢?
【问题讨论】:
-
没关系,但你为什么忽略
-mavx2?无论如何,您应该使用-march=native来启用您的 CPU 可以使用的所有功能,更重要的是为该 CPU 调整,而不是仍然为通用基线 CPU 进行调整。 -
您是否尝试在最内层范围内声明变量,因此每个循环迭代都有自己的
__m256d va = _mm256_loadu_pd(&a[m*k+i]);,以及自己的i和for (int i = 0 ; ...)? IDK OpenMP 很好,所以 IDK 是否会有所作为,但似乎完全没有必要单独声明任何这些变量。 -
我猜您使用的是列优先顺序 (en.wikipedia.org/wiki/Row-major_order)?这在 Fortran 中很正常,但在 C 中则不然。
-
那么,你的意思是我应该使用 Fortran 以便使用 openmp 进行并行化吗?
-
@Mic,没有“这在 Fortran 中很正常,但在 C 中不正常”是一个愚蠢的评论。如果您在 C 中使用静态或堆栈分配的二维数组,则它是行主要排序。但是,如果您动态分配内存,您可以使用任何您喜欢的顺序。我只是不习惯看到列主要排序。但是您应该声明您在问题中使用了列主要排序,否则我认为大多数人会假设行主要排序。
标签: c multithreading openmp avx2