2016/01/13

Raspberry Pi:安裝並測試MPICH

MPI(Message Passing Interface,訊息傳遞介面),可讓運算叢集裡不同節點的程式,互相傳遞訊息,藉以達到平行處理的目標,加快執行速度。

較知名的實作有MPICHOpen MPI,支援語言Fortran、C、C++,但可透過其他實作或綁定(binding)支援別的語言,如Python、Java、等等。MPICH資歷較久,資源較多,所以這一篇介紹MPICH。

這一篇將會記錄如何安裝MPICH,並執行測試用範例程式,確認可正常運作。我的環境是4台Raspberry Pi Model B+與Raspbian Jessie Lite(2015-11-21)。

燒錄、開機並完成初始設定(區域設置、時區等等),然後先更新套件清單並升級:
~ $ sudo apt-get update
~ $ sudo apt-get dist-upgrade -y

安裝C編譯器gcc、C++編譯器g++,但發現預設已安裝:
~ $ sudo apt-get install gcc g++

之後也會執行Fortran測試程式,所以要安裝Fortran編譯器gfotran
~ $ sudo apt-get install gfortran

在家目錄/hom/pi底下建立目錄mpich3,並進入,
~ $ mkdir mpich3
~ $ cd mpich3

建立子目錄build作為建置目錄,用來存放建置時產生的檔案,跟原始碼目錄分開來,讓原始碼目錄保持乾淨。
~/mpich3 $ mkdir build

建立安裝目錄,之後會把建置好的東西(腳本檔、執行檔)放在這裡;之後會指定安裝路徑,這麼一來,你便可試著修改建置參數,建置後安裝到不同路徑,測試效能表現的差異。我放在/usr/local/bin/mpich32。
~/mpich3 $ sudo mkdir /usr/local/bin/mpich32

下載MPICH原始碼壓縮檔,我下載的版本是3.2,解壓縮後得到含有原始碼的子目錄mpich-3.2。請自行到MPICH官方網站查詢最新版本與下載網址。
~/mpich3 $ wget http://www.mpich.org/static/downloads/3.2/mpich-3.2.tar.gz
~/mpich3 $ tar zxvf mpich-3.2.tar.gz

接下來要建置與安裝,主要有三個步驟,執行configure並設定參數,執行make進行建置,最後執行make install安裝。

切換到子目錄build,執行指令configure並設定參數,
~/mpich3 $ cd build
~/mpich3/build $ /home/pi/mpich3/mpich-3.2/configure --prefix=/usr/local/bin/mpich32 2>&1 | tee log_c.txt

其中「2>&1」代表把標準錯誤導向標準輸出,「| tee log_c.txt」則是把左邊指令的標準輸出丟給指令tee,tee除了會輸出到螢幕(標準輸出),也會複製一份輸出到檔案log_c.txt,出問題時可到此查看。

請依需求為configure設定參數,主要參數如下:

  • --prefix:指定安裝路徑,預設/usr/local/bin。
  • --disable-cxx:去掉MPI的C++介面。
  • --disable-f77:去掉MPI的Fortran 77或90介面。
  • --disable-fc:不支援Fortran 90,或之後的版本95、2003、2008。
  • CC=xyz、CXX=xyz、F77=xyz、FC=xyz:自行指定編譯器。
  • --enable-fast,最快效能表現,但會降低錯誤回報能力,建議用於已確認沒問題的程式。
  • --with-pm=,選擇行程管理員,有hydra(預設)、gforker、remshell可選。
  • --with-device=,選擇溝通裝置,有ch3:nemesis(預設)、ch3:sock可選。
參數非常多,會影響效能表現,譬如若只有一台多核心處理器的機器,行程管理員似乎應選gforker比較好。還請查詢官方文件,執行configure -h可列出所有參數。

然後開始建置,嘿,這可需要不少時間喔,泡杯茶或咖啡吧;若出錯,可試著加上VERBOSE=1,輸出更詳細的訊息。
~/mpich3/build $ make 2>&1 | tee log_m.txt

(若以一台Pi 2建置,大約花60分鐘。我以四台Model B+運用distcc分散編譯工作,約花85分鐘。)

然後安裝,
~/mpich3/build $ sudo make install 2>&1 | tee log_i.txt 

接下來設定執行路徑,修改~/.profile,在最後面加上底下這行,
export PATH="$PATH:/usr/local/bin/mpich32/bin"

登出再登入,執行底下指令確認可找到MPICH的執行檔,
~/mpich3/build $ cd
~ $ which mpicc
/usr/local/bin/mpich32/bin/mpicc
~ $ which mpiexec
/usr/local/bin/mpich32/bin/mpiexec

試著執行底下的指令,其中「-n 2」代表兩個行程:
~ $ mpiexec -n 2 hostname
raspberrypi
raspberrypi

執行指令mpichversion的話,可看到建置時的參數,
~ $ mpichversion
MPICH Version:          3.2
MPICH Release date:     Wed Nov 11 22:06:48 CST 2015
MPICH Device:           ch3:nemesis
MPICH configure:        --prefix=/usr/local/bin/mpich32
MPICH CC:       gcc    -O2
MPICH CXX:      g++   -O2
MPICH F77:      gfortran   -O2
MPICH FC:       gfortran   -O2


完成後,如果你有多台rpi,應把目錄/usr/local/bin/mpich32複製到別台rpi,並且修改執行路徑。

接著要讓各台機器能夠以SSH互相登入,在此不詳細解釋,總之就是要做到以SSH登入、毋須輸入密碼。否則之後會出現錯誤訊息「Host key verification failed.」。

新增檔案machinefile,裡頭每行填入有安裝MPICH的rpi的IP位址,格式如下:
192.168.1.21
192.168.1.22:1
192.168.1.23:2
192.168.1.24:4

我有四台rpi,IP位址分別是192.168.1.21、22、23、24。

其中「:4」代表在該台機器上執行4個行程,預設是1個。然後以「-f machinefile」指定把任務分配到檔案裡的機器。

先以MPICH附帶的測試程式cpi為例,計算圓周率π,
~ $ mpiexec -f machinefile -n 9 ./mpich3/build/examples/cpi
Process 7 of 9 is on rpi_p1
Process 0 of 9 is on rpi_p1
Process 8 of 9 is on rpi_p2
Process 2 of 9 is on rpi_p3
Process 1 of 9 is on rpi_p2
Process 6 of 9 is on rpi_p4
Process 3 of 9 is on rpi_p3
Process 4 of 9 is on rpi_p4
Process 5 of 9 is on rpi_p4
pi is approximately 3.1415926544231261, Error is 0.0000000008333330
wall clock time = 0.078139


執行mpiexec --help可查詢其他參數。

接下來試著自己撰寫MPI程式,首先是C語言,新增檔案hello_mpi.c,內容如下:
#include <stdio.h>
#include <mpi.h>

int main(int argc, char *argv[])
{
  int n;
  int total;

  MPI_Init(&argc, &argv);

  MPI_Comm_rank(MPI_COMM_WORLD, &n);
  MPI_Comm_size(MPI_COMM_WORLD, &total);
  printf("This is Raspberry Pi %d of %d\n", n+1, total);

  MPI_Finalize();

  return 0;
}

編譯,
~ $ mpicc -o hello_mpi hello_mpi.c

若有多台rpi,須把執行檔複製過去,然後再執行,
~ $ mpiexec -f machinefile -n 6 ./hello_mpi
This is Raspberry Pi 3 of 6
This is Raspberry Pi 4 of 6
This is Raspberry Pi 2 of 6
This is Raspberry Pi 5 of 6
This is Raspberry Pi 6 of 6
This is Raspberry Pi 1 of 6

然後是Fortran語言,新增檔案himpi.f,內容如下:
       program himpi
       include 'mpif.h'

       integer n, total, err


       call MPI_INIT(err)

       call MPI_COMM_RANK(MPI_COMM_WORLD, n, err)
       call MPI_COMM_SIZE(MPI_COMM_WORLD, total, err)

       print *, 'This is Raspberry Pi ',(n+1),' of ',total


       call MPI_FINALIZE(err)

       end

編譯,
~ $ mpif90 -o himpi himpi.f

若有多台rpi,須把執行檔複製過去,然後才能執行:
~ $ mpiexec -f machinefile -n 4 ./himpi
 This is Raspberry Pi            3  of            6
 This is Raspberry Pi            4  of            6
 This is Raspberry Pi            5  of            6
 This is Raspberry Pi            6  of            6
 This is Raspberry Pi            1  of            6
 This is Raspberry Pi            2  of            6


呼~結束囉。


參考資料:

7 comments:

  1. 哇~樹莓派居然還可以跑fortran這種語言很古老了,只有在工作站裡做數學模型模擬時,才會去用,我那時候用是因為教授規定用fortran寫FFT的程式(我懷疑教授只會用Fortran),其實很久沒用的,如果現在看到大概都是有看沒懂....依照這兩個範例,應該也可以類推python要平行運行也是可以採用相同的方法.

    ReplyDelete
    Replies
    1. Fortran雖老,但依然健在。

      MPI有Python語言綁定。

      Delete
  2. IT automation with Ansible on a cluster of 6 Raspberry Pi computers | Opensource.com

    https://opensource.com/life/16/2/cluster-computing-with-ansible-and-raspberry-pi

    ReplyDelete
  3. Erlang : Pi2 ARM cluster vs Xeon VM
    https://medium.com/@pieterjan_m/erlang-pi2-arm-cluster-vs-xeon-vm-40871d35d356#.d5mqi6gr9

    比較rpi2與xeon的運算叢集。

    ReplyDelete
  4. DIY 5 Node Cluster of Raspberry Pi 3s | Climbers.net
    http://climbers.net/diy-raspberry-pi-3-cluster/

    ReplyDelete
  5. 很棒, 網路找到的MPI資料都很老舊(2003前後), 這篇資料真的很新, 很寶貴,
    不知是否能示範在Windows虛擬機上架設多台Ubuntu執行MPI例子的計算

    ReplyDelete
    Replies
    1. > 老舊
      或可參閱 http://www.dursi.ca/hpc-is-dying-and-mpi-is-killing-it/

      > 不知是否能
      不能。

      Delete