簡體   English   中英

使用openmp進行LU分解

[英]LU decomposition using openmp

我有一個問題: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倍。

雙線程有很多同步開銷,這可能會減慢您的速度,尤其是在向量化松動的情況下。 同樣由於某種原因,除非調用omp_set_num_threads使其實際使用線程,否則#pragma omp不會啟動任何線程。

與向量化也有關的另一件事是,並非所有編譯器都了解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

如您所見,我對向量化器做了一些改進,但對並行部分並沒有做太多的事情。

您的代碼的主要問題是您以不良的方式分解了工作負載。

對於單個LU分解,您將並行調用n-1次。 每次,parallel for都會進行線程派生和聯接,這會帶來很多開銷。 特別是當k大時,內部循環( for(i){for(j){...}} )僅包含很少的工作。 並行處理將非常低效。

您可以考慮使用適當的集聚方案以減少開銷。 有關更多信息,請參閱此幻燈片。

http://courses.engr.illinois.edu/cs554/notes/06_lu_8up.pdf

另一方面,您可以使用現有的性能庫來獲得LU分解的最高性能,例如Intel MKL

http://software.intel.com/en-us/node/468682

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM