Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 基于openmp的LU分解_C++_C_Openmp_Linear Algebra - Fatal编程技术网

C++ 基于openmp的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

我有一个问题: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];
        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