Hypre與Petsc安裝文檔及性能測試

1. 前言

本文介紹了并行計算庫的Hypre和Petsc的安裝方法以及在線性系統(tǒng)求解中不同算法的性能測試,用于日后在不同系統(tǒng)上的Hypre和Petsc的安裝需要和新型算法性能測試基準。程序安裝運行環(huán)境為NVIDIA-dgx1,詳細參數(shù)請見dgx1參數(shù)。本文將分為Hypre和Petsc兩個部分,分別以總體介紹,安裝,程序運行關(guān)鍵代碼和在IEEE不同節(jié)點數(shù)據(jù)下性能測試的順序介紹兩款軟件的使用。

2. Hypre介紹,安裝及使用

2.1 Hypre介紹

2.1.1 性能介紹

Hypre是運行在多核處理器上,借助目前性能較好的預(yù)處理矩陣(preconditioner)對于大型稀疏線性方程組使用迭代法求解的一個c語言庫。其基本目標是讓用戶可以借助于多核處理器的并行性能,并行存儲矩陣不同范圍的信息,并行地進行迭代法求解,從而達到事半功倍的效果。Hypre具有擴展性極強的預(yù)處理矩陣算法,對于大型系統(tǒng)的預(yù)處理矩陣生成也有著不錯的性能,并且迭代法所用算法選擇空間較大,從后續(xù)的測試結(jié)果也可以看到,在選擇了合適的算法的情況下,對于實際的電力系統(tǒng)線性方程組求解也可以有較快的計算速度。

另一方面,從用戶的使用角度來講,用戶無需預(yù)先學(xué)習(xí)復(fù)雜的稀疏矩陣存儲,而只需分配對應(yīng)行列坐標給矩陣類,之后的空間壓縮操作都可以由Hypre完成,這對于新手來說,可以在最短時間內(nèi)搭好自己的第一個求解線性方程組程序,是很好的入門函數(shù)庫。

2.1.2 程序框架介紹

Hypre使用了“原型”的概念,這個概念對于程序來說,是一種儲存信息的統(tǒng)一格式,可以更為高效地分配存儲空間。在編程之前,用戶需要決定對于自己的問題,使用哪一種原型來存儲信息。其包括:

  • Structured-Grid System Interface

    這是應(yīng)用于矩陣中非零元素十分規(guī)則,可以用Stencil類型來統(tǒng)一表示非0元素分布的系統(tǒng)。其中Stencil類型使用的相對坐標位置的方法,在確定中心點的情況下(0,0),使用對應(yīng)坐標來確定非零元素的位置和值,并且在矩陣的賦值過程得以使用。

  • Linear-Algebraic System Interface (IJ)

    IJ適用于一般的線性系統(tǒng),這類系統(tǒng)非零元素的分布沒有規(guī)律可循,我們可以通過按行賦值的方式存儲矩陣中非零元素的信息。而在賦值完畢后,程序?qū)⑹褂肅SR的格式存儲非零元素的信息。

在線程的資源分配上,Hypre也采用了相對坐標的方式?jīng)Q定一個線程擁有的矩陣信息范圍。使用左下角的坐標點和右上角的坐標點,Hypre可以通過他們的差值來得出其擁有的矩陣范圍。另一方面,Hypre也可以通過行坐標的范圍,來決定各線程所分配到矩陣范圍。用戶可以通過自身系統(tǒng)的特點,來判斷到底采取哪一種分配方式。

2.1.3 用戶使用的Hypre的總體步驟

綜上,在使用Hypre計算線性系統(tǒng)方程時,需要包括以下步驟:

  • 根據(jù)系統(tǒng)特點,選擇不同的原型結(jié)構(gòu)
  • 根據(jù)該結(jié)構(gòu),對系統(tǒng)生成的矩陣進行賦值
  • 為系統(tǒng)不同的線程分配屬于該線程的系統(tǒng)信息
  • 選用合適的方法與preconditioner進行求解
  • 獲取結(jié)果

2.2 Hypre安裝

2.2.1 檢查openmpi安裝

  • 首先檢查系統(tǒng)中是否存在openmpi:

    $ mpirun --version
    
    • 如果存在則直接去安裝Hypre,否則先安裝openmpi(本文檔選用的版本是openmpi v1.10)。

2.2.2 安裝openmpi

  • 進入openmpi官網(wǎng)(https://www.open-mpi.org/software/ompi/v1.10/),下載.tar.gz文件到本地。

  • 在下載路徑下,解壓該tar.gz文件

    $ tar -zxvf openmpi-1.10.7.tar.gz
    
  • 進入解壓后生成的文件夾

    $ cd openmpi-1.10.7
    
  • configure路徑下的文件,注意"--prefix="指定的是安裝路徑,用戶可以自己指定,在后面找得到就行。

    $ ./configure --prefix="/usr/local/openmpi"
    
  • 編譯并安裝

    $ make 
    $ sudo make install
    
  • 為openmpi設(shè)置環(huán)境變量,進入~/.bashrc加入如下內(nèi)容后保存并source

    $ vim ~/.bashrc
    /* 以下內(nèi)容在.bashrc中更改 */
    export PATH="$PATH:/usr/local/openmpi/bin"
    export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/openmpi/lib/"
    /****************************************************************/
    $ source ~/.bashrc
    
  • 測試是否安裝成功:進入openmpi解壓的文件夾中有一個examples,運行如下例程將為出現(xiàn)兩行"hello",則表示安裝成功

    $ mpirun -np 2 ./hello_c
    

2.2.3 安裝Hypre

  • 進入Hypre的github中clone源代碼

    $ git clone https://github.com/LLNL/hypre.git
    // 進入source code文件夾
    $ cd hypre/src
    
  • 注意在configure的時候要讓hypre知道Openmpi在哪

    $ ./configure -prefix=/usr/local/hypre \
        -with-MPI-include=/usr/local/openmpi/include \
        -with-MPI-libs="mpi_cxx mpi" \
        -with-MPI-lib-dirs=/usr/local/openmpi/lib
    
  • 編譯安裝

    $ sudo make install
    

    需要一段時間。。。

  • 在src文件夾中有一個examples文件夾,里面有測試是否安裝成功的例程。在使用Makefile編譯后,生成的可執(zhí)行文件需要mpirun運行。

    $ make
    $ mpirun -np 2 ex1(ex2)
    

    如果正常輸出,則表示安裝成功。

2.3 Hypre計算代碼詳解

2.3.1 Hypre線程分配空間方式

在將矩陣不同行分給hypre不同線程時,需要告知該線程矩陣的起始行終止行,在已知矩陣總行數(shù)(N)和處理器個數(shù)(線程個數(shù) num_procs)的情況下,考慮N無法被num_procs整除的情況,可以得到如下的計算公式。其中,myid表示這是第幾個線程。

local_size = N / num_procs;         // size per processor
extra = N - local_size * num_procs; // consider rows cannot be fully divided by procs
ilower = local_size * myid;
ilower += hypre_min(myid, extra);
iupper = local_size * (myid + 1);
iupper += hypre_min(myid + 1, extra);
iupper = iupper - 1;
// update num of rows
local_size = iupper - ilower + 1;

2.3.2 Hypre矩陣,向量儲存形式和賦值

目前Hypre支持的存儲形式為HYPRE_PARCSR,矩陣類為HYPRE_IJMatrix,和HYPRE_IJVector,經(jīng)過print打出之后為“行,列,值”的坐標對。矩陣賦值支持按行賦值

HYPRE_IJMatrixSetValues(ij_matrix, nrows, ncols, rows, cols, values);
// 其中,ij_matrix為矩陣地址,nrows是賦值的行數(shù),ncols為該行非0元素個數(shù),rows為行坐標,cols為列作標,values為所賦的非0值

Vector的賦值與上述矩陣賦值相似。

另一方面,需要注意在每次賦值前都需要initialize矩陣,賦值完畢后都需要assemble矩陣,并且獲取控制該矩陣的句柄。

HYPRE_IJMatrixInitialize(A);
/* ... 賦值操作 ... */
HYPRE_IJMatrixAssemble(A);
HYPRE_IJMatrixGetObject(A, (void **)&parcsr_A);

2.4 Hypre求解線性系統(tǒng)性能測試

<table>
<thead>
<td>計算題目</td>
<td>計算方法</td>
<td>迭代次數(shù)</td>
<td>計算時間</td>
</thead>

<tr>
    <td rowspan="4"> 14節(jié)點<br/>
</tr>
<tr>
    <td> PCG </td>
    <td> 13 </td>
    <td> 0.000860s </td>
</tr>
<tr>
    <td> AMG </td>
    <td> 5 </td>
    <td> 0.000328s </td>
</tr>
<tr>
    <td> PCG with AMG preconditioner </td>
    <td> 4 </td>
    <td> 0.000310s </td>
</tr>

<tr>
    <td rowspan="4"> 118節(jié)點<br/>
</tr>
<tr>
    <td> PCG </td>
    <td> 117 </td>
    <td> 0.001329s </td>
</tr>
<tr>
    <td> AMG </td>
    <td> 10 </td>
    <td> 0.000752s </td>
</tr>
<tr>
    <td> PCG with AMG preconditioner </td>
    <td> 6 </td>
    <td> 0.000787s </td>
</tr>   

<tr>
    <td rowspan="4"> 10790節(jié)點<br/>
</tr>
<tr>
    <td> PCG </td>
    <td> 6207 </td>
    <td> 0.9464s </td>
</tr>
<tr>
    <td> AMG </td>
    <td> 12 </td>
    <td> 0.0337s </td>
</tr>
<tr>
    <td> PCG with AMG preconditioner </td>
    <td> 7 </td>
    <td> 0.0284s </td>
</tr>

<tr>
    <td rowspan="4"> 
        福建1425節(jié)點
    <br/>
</tr>
<tr>
    <td> PCG </td>
    <td> 21246 </td>
    <td> 0.388728s </td>
</tr>
<tr>
    <td> AMG </td>
    <td> 迭代發(fā)散 </td>
    <td> NA </td>
</tr>
<tr>
    <td> PCG with AMG preconditioner </td>
    <td> 375 </td>
    <td> 0.061298s </td>
</tr>

<tr>
    <td rowspan="4"> 四川2433節(jié)點 <br/>
</tr>
<tr>
    <td> PCG </td>
    <td> 16705 </td>
    <td> 0.496167s </td>
</tr>
<tr>
    <td> AMG </td>
    <td> 迭代發(fā)散 </td>
    <td> NA </td>
</tr>
<tr>
    <td> PCG with AMG preconditioner </td>
    <td> 10000(迭代未結(jié)束但結(jié)果誤差在0.01級別) </td>
    <td> 2.464774s </td>
</tr>

</table>

3. PETSC的安裝及使用

3.1 PETSC安裝

3.1.1 下載PETSC安裝包

說明:本部分基于機器上已經(jīng)安裝有openmpi,如果沒有,請移步“安裝openmpi”部分。

  • 使用git clone下載petsc源碼
$ git clone -b maint https://bitbucket.org/petsc/petsc petsc

3.1.2 安裝PETSC

  • 在源代碼根目錄下,編譯源碼,假設(shè)你的openmpi裝在了“/usr/local/openmpi”里面,你想把petsc裝在“$HOME/petsc”下:
$ ./configure --with-mpi-dir=/usr/local/openmpi/ --download-fblaslapack --prefix=$HOME/petsc
  • 測試安裝是否成功
$ make all test

3.1.3 運行PETSC程序

  • 源代碼中有一些example的文件,假定你已經(jīng)在petsc根目錄下面,examples的文件在 “./src/snes/examples/tutorials/”中。注意在make的時候需要指定PETSC_DIR和PETSC_ARCH中的路徑。PETSC_DIR就是petsc的根目錄,PETSC_ARCH是名字帶“ARCH”的文件夾。假設(shè)你要編譯ex12.c的文件夾
# 編譯
$ make PETSC_DIR=$HOME/iterative/petsc PETSC_ARCH=arch-linux2-c-debug ex12
# mpi運行, -n 為指定processor數(shù)量
$ mpiexec -n 4 ./ex12

3.2 PETSC計算代碼詳解

3.2.1 PETSC線程分配空間方式

與Hypre不同的是,PETSC無需顯式地表達分配給該線程的矩陣/向量行坐標范圍,而只需告訴PETSC矩陣的行數(shù)和列數(shù),使用PETSC_DECIDE讓PETSC自行決定分配給該線程的行坐標范圍,并且可以通過內(nèi)置的函數(shù)來獲得屬于該線程的起始坐標和結(jié)束坐標。以下為示例代碼:

// A為matrix
ierr = MatSetSizes(A, PETSC_DECIDE, PETSC_DECIDE, numRow, numCol);
/*...矩陣操作...*/
ierr = MatGetOwnershipRange(A, &Istart, &Iend);

值得一提的是,PETSC中大部分的函數(shù)操作均會返回該操作的狀態(tài)碼,可以通過

CHKERRQ(ierr)

來檢查程序是否出錯。推薦每做一次操作都要檢查一次狀態(tài)碼。

3.2.2 PETSC矩陣,向量儲存形式和賦值

PETSC存儲矩陣的類型為Mat,存儲向量的類型為Vec,在矩陣賦值時,需要告知行坐標,賦值個數(shù),和所賦的值。

ierr = MatSetValues(A, 1, &Ii, 1, &J, &v, INSERT_VALUES);

其中INSERT_VALUES表示賦值類型,代表將該坐標上的參數(shù)設(shè)為v。而在每次賦值完畢后,都需要Assemble矩陣來告知系統(tǒng)矩陣賦值已完成。

// assemble matrix A
ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);
CHKERRQ(ierr);
ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);
CHKERRQ(ierr);

3.3 PETSC求解線性系統(tǒng)性能測試

目前PETSC只能支持PCG的求解,如若要使用AMG的求解需要自行編寫相關(guān)的代碼,因此,本文只在PETSC測試中,使用了PCG的求解方法進行性能測試。

計算題目 迭代次數(shù) 計算時間
14節(jié)點 13 0.001009s
118節(jié)點 78 0.004705s
10790節(jié)點 2257 0.911253s
福建1425節(jié)點 發(fā)散 NA
四川2433節(jié)點 發(fā)散 NA

4 結(jié)論

本測試報告詳細總結(jié)了并行計算庫Hypre,PETSC的安裝和求解線性方程組的過程,并且在不同的線性系統(tǒng)問題上進行了性能測試。測試結(jié)果表明,Hypre對于實際系統(tǒng)的適應(yīng)度較高,在算法選擇上多樣,并且在合適的preconditioner的幫助下,對于實際系統(tǒng)方程的求解也會有比較好的性能。而PETSC在一些算法的開發(fā)的上仍然存在不足,如AMG的算法需要自行編寫。并且在實際系統(tǒng)環(huán)境下的線性方程組求解上,無法獲得比較好的結(jié)果。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容