C++ 基于openmp的LU分解
我有一个问题:LU分解算法的并行版本与序列运行的时间相同:C++ 基于openmp的LU分解,c++,c,openmp,linear-algebra,C++,C,Openmp,Linear Algebra,我有一个问题:LU分解算法的并行版本与序列运行的时间相同: void lup_od_omp(double* a, int n){ int i,j,k; for(k = 0; k < n - 1; ++k) { #pragma omp parallel for shared(a,n,k) private(i,j) for(i = k + 1; i < n; i++) { a[i*n + k] /= a[k*n + k]; fo
void lup_od_omp(double* a, int n){
int i,j,k;
for(k = 0; k < n - 1; ++k)
{
#pragma omp parallel for shared(a,n,k) private(i,j)
for(i = k + 1; i < n; i++)
{
a[i*n + k] /= a[k*n + k];
for(j = k + 1; j < n; j++)
{
a[i*n + j] -= a[i*n + k]*a[k*n + j];
}
}
}}
void lup\u od\u omp(双*a,整数n){
int i,j,k;
对于(k=0;k
也许我做错了什么?代码的主要问题是您以一种糟糕的方式分解了工作负载 对于单个LU分解,调用parallel的次数为
n-1次。每次,parallel for都会执行线程fork和join,这会引入大量开销。特别是当k
很大时,内部循环(for(i){for(j){…}
)只包含很少的功。与之并行将是相当低效的
你可以考虑使用适当的凝聚方案来降低开销。有关更多信息,请参阅本幻灯片
另一方面,您可以使用现有的性能库来获得LU因式分解的最大性能,例如Intel MKL
由于您只在两个内核上工作,因此并行化实际上可能会妨碍矢量器。SSE2上的矢量化将为您提供每个op 2倍的数据带宽,AVX上为4倍
双线程有大量的同步开销,这可能会减慢速度,特别是如果您松开矢量化。此外,出于某种原因,除非调用omp\u set\u num\u threads
使其实际使用线程,否则您的#pragma omp
不会启动任何线程
另一件与矢量化相关的事情是,并非所有编译器都理解a[i*n+j]
用于处理二维数组,因此最好首先声明它是这样的
下面是对您的代码进行的一点轻微优化,它在my 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];
}
}
}
}
在另一台机器上,我在AVX上测试了它(256位向量,每运算4倍):
正如您所看到的,我对矢量器做了一些改进,但对并行部分没有做太多。单线程版本运行多长时间?与并行时间相同:~8s用于2000*2000矩阵您有多少CPU内核?您使用哪种操作系统/编译器?您是否在编译器中启用了openmp支持?您存在错误共享的主要问题。但除此之外:您在哪里使用p
?更高的优化级别可能会有所帮助。我使用gcc
/icc
,得到了类似的结果,但在启用openmp、sse2、fp模式时,使用VS2010绝对不会提高性能:对您的代码和他的代码进行快速和全面优化。此代码在哪个操作系统上进行过测试?我已经在Windows上使用MinGW测试过它:没有-O或-O2标志,Parralle速度更快,但如果启用其中一个标志,并行时间等于或大于序列时间……WinXP和VS2010,在启用sse2时,序列和4线程版本的时间相等。“出于某种原因,除非调用omp#u set_num_threads使其实际使用线程,否则您的#pragma omp不会启动任何线程。”这通常不正确。(对于英特尔编译器肯定不正确;默认情况下,我们将为每个可用的逻辑处理器创建一个线程)@JimCownie在我设置环境变量OMP_NUM_THREADS=8
之前并不适用于我,尽管所有其他代码默认使用8个线程运行。
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
My code on AVX sequential : 0:09.45 99% CPU
My code on AVX 8 threads : 0:03.92 766% CPU