c++ - 使用 openmp 进行 LU 分解

标签 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];
        for(j = k + 1; j < n; j++)
        {
            a[i*n + j] -= a[i*n + k]*a[k*n + j];
        }
    }
}}

也许我做错了什么?

最佳答案

由于您只在两个内核上工作,您的并行化实际上可能会妨碍向量化器。 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 位 vector ,每个操作 4 个 double ):

My code on AVX sequential :  0:09.45 99%  CPU
My code on AVX 8 threads  :  0:03.92 766% CPU

如您所见,我对矢量化器做了一些改进,但对并行部分的改进不大。

关于c++ - 使用 openmp 进行 LU 分解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19365277/

相关文章:

c++ - 如何在不使用原子的情况下同步 CUDA 中的线程

C:检查一个数组只包含 0-7 范围内的数字

为包含指针引用的已分配内存的结构释放内存的正确方法

c - OpenMP time 和 clock() 给出了两个不同的结果

c++ - 修改后的动态背包 - 有问题的输入?

c++ - 从C迁移到C++

c++ - 我如何替换集合中的元素?

c++ - volatile关键字有什么用?

python - cython错误无法分配给外部并行 block 的私有(private)

C OMP omp_get_wtime() 返回时间 0.00