由于您只在两个内核上工作,因此您的并行化实际上可能会妨碍矢量化器。SSE2 上的矢量化将为您提供每个操作 2 双倍的数据带宽,在 AVX 上为 4。
双线程有很多同步开销,这可能会减慢您的速度,尤其是在您松散矢量化的情况下。同样由于某种原因,除非被调用以使其实际使用线程,否则您#pragma omp
不会启动任何线程。omp_set_num_threads
与向量化相关的另一件事是,并非所有编译器都理解它a[i*n + j]
旨在解决二维数组,因此最好首先将其声明为这样。
这是对您的代码的轻微优化,在我的 Xeon 上运行得相当好:
void lup_od_omp(int n, double (*a)[n]){
int i,k;
for(k = 0; k < n - 1; ++k) {
// for the vectoriser
for(i = k + 1; i < n; i++) {
a[i][k] /= a[k][k];
}
#pragma omp parallel for shared(a,n,k) private(i) schedule(static, 64)
for(i = k + 1; i < n; i++) {
int j;
const double aik = a[i][k]; // some compilers will do this automatically
for(j = k + 1; j < n; j++) {
a[i][j] -= aik * a[k][j];
}
}
}
}
3000x3000 数组的运行时icc -O2
:
Your code sequential: 0:24.61 99% CPU
Your code 8 threads : 0:05.21 753% CPU
My code sequential: 0:18.53 99% CPU
My code 8 threads : 0:05.42 766% CPU
在另一台机器上,我在 AVX 上对其进行了测试(256 位向量,每个操作 4 个双精度):
My code on AVX sequential : 0:09.45 99% CPU
My code on AVX 8 threads : 0:03.92 766% CPU
正如你所看到的,我对矢量化器做了一些改进,但对并行部分并没有做太多。