现有串行代码矩阵分解计算多线程使用OpenMP案例

Case of using OpenMP for multi-threading of a matrix factorization calculation of an existing serial code

我遇到了一个代码,该代码使用低性能系列 for 循环来计算所谓的“Crout 分解”。如果您需要了解更多,我认为这个概念类似于 described here。 乍一看,代码是一个 for 循环,可以通过 omp 指令简单地变为并行:

SparseMtrx *Skyline :: factorized()
{
    // Returns the receiver in  U(transp).D.U  Crout factorization form.
        ...
        // this loop is very expensive and only uses single thread:
        for ( int k = 2; k <= n; k++ ) {
            int ack = adr.at(k);
            int ack1 = adr.at(k + 1);
            int acrk = k - ( ack1 - ack ) + 1;
            for ( int i = acrk + 1; i < k; i++ ) {
                int aci = adr.at(i);
                int aci1 = adr.at(i + 1);
                int acri = i - ( aci1 - aci ) + 1;
                int ac;
                if ( acri < acrk ) {
                    ac = acrk;
                } else {
                    ac = acri;
                }
    
                int acj = k - ac + ack;
                int acj1 = k - i + ack;
                int acs = i - ac + aci;
                double s = 0.0;
                for ( int j = acj; j > acj1; j-- ) {
                    s += mtrx [ j ] * mtrx [ acs ];
                    acs--;
                }
    
                mtrx [ acj1 ] -= s; //mtrx  here is the matrix values (shared)
            }
            double s = 0.0;
            for ( int i = ack1 - 1; i > ack; i-- ) {
                double g = mtrx [ i ];
                int acs = adr.at(acrk);
                acrk++;
                mtrx [ i ] /= mtrx [ acs ];
                s += mtrx [ i ] * g;
            }
    
            mtrx [ ack ] -= s;
        }
    ...

但问题是似乎每一步都使用矩阵值的更新值 mtrx 来计算下一个分解值。

我的问题是有什么方法可以使用多线程来做这个计算吗?

完整代码可通过 this link 在 github 中获得。

Crout 分解是高斯消去法的一种变体。您可以通过 1. 它们的 end-product 2. 它们的处理方式来描述此类算法。 Crout 分解计算 LU,其中 U 的对角线是恒等式。其他因式分解对 L 的对角线进行归一化,或者它们计算 LDU 时 L,U 都被归一化,或者它们计算 LU 时 L 和 U 的对角线相等。所有这些都与并行化无关。

接下来,您可以通过计算方式来描述高斯消除算法的特征。这些都是基本三重嵌套循环在数学上等价的re-organizations。由于它们在数学上是等价的,您可以选择一个或另一个以获得有利的计算特性。

要解决一件事:高斯消元法在计算枢轴时具有本质上的顺序成分,因此您无法使其完全并行。 (好吧,有些关于行列式的嘀咕,但那是不现实的。)外循环是连续的,步数等于矩阵大小。问题是你是否可以使内部循环并行。

Crout 算法的特点是,在分解的步骤“k”中,它计算 U 的行“k”和 L 的列“k”。由于两者中的元素不递归相关,因此这些更新可以在并行循环中完成,它为您提供了一个顺序的“k”循环,并且对于每个 k 值,有两个并行的单循环。这就剩下第三个循环级别:那个循环级别来自这样一个事实,即每个独立的迭代都涉及一个总和,因此是一个缩减。

这听起来不太适合并行化:如果内部是缩减,则不能 collapse 两个循环,因此您必须选择要并行化的级别。也许您应该使用不同的高斯消去公式。例如,普通算法基于“rank-k 更新”,并且这些算法非常并行。该算法有一个顺序循环,每个步骤都有一个 collapse(2) 并行循环。