wiki:YM_Course_2009/Lab8
實作八: MPICH 實作練習

實作八 ('MPI完全解說'版本) - 課程投影片

◢ <實作七> | <回課程大綱> ▲ | <實作九> ◣

MPI 環境設定

  • 使用你的帳號登入: ym
    login as: ym24
    ym24@bio.classcloud.org's password: ******
    ym24@bio001:~$ ssh-keygen -t rsa
    
  • 產生 SSH 認證金鑰
    Generating public/private rsa key pair.
    Enter file in which to save the key (/home/ym24/.ssh/id_rsa):  <<< 請按 Enter
    Created directory '/home/ym24/.ssh'.
    Enter passphrase (empty for no passphrase):            <<< 請按 Enter
    Enter same passphrase again:                     <<< 請按 Enter
    Your identification has been saved in /home/ym24/.ssh/id_rsa.
    Your public key has been saved in /home/ym24/.ssh/id_rsa.pub.
    The key fingerprint is:
    2a:6c:05:f8:24:38:db:79:b9:4f:0c:74:da:c5:16:05 ym24@bio001
    
  • 進行金鑰交換
    ym24@bio001:~$ cp .ssh/id_rsa.pub .ssh/authorized_keys
    
  • 設定 MPD 設定檔跟 MPI 的執行檔路徑
    ym24@bio001:~$ echo "MPD_SECRETWORD=${user}$$" > ~/.mpd.conf
    ym24@bio001:~$ chmod 600 .mpd.conf
    ym24@bio001:~$ for ((i=2;i<=12;i++)); do echo "192.168.129.$i" >> mpd.hosts; done
    ym24@bio001:~$ export PATH=$PATH:/opt/mpich2/bin
    ym24@bio001:~$ which mpdboot
    /opt/mpich2/bin/mpdboot
    
  • 設定 dsh (distributed shell)*, 我們可以使用 dsh 指令逐台執行.
    ym24@bio001:~$ mkdir -p .dsh/
    ym24@bio001:~$ cp mpd.hosts .dsh/machines.list
    ym24@bio001:~$ dsh -a hostname
    
  • 用使用者的身分執行 mpd
    ym24@bio001:~$ mpdboot -n 7
    
  • 用 mpdtrace 檢查 mpd 執行狀態
    ym24@bio001:~$ mpdtrace 
    bio002
    bio006
    bio012
    bio011
    bio005
    bio004
    bio003
    bio010
    bio009
    bio008
    bio007
    
  • 用 mpdringtest 做 mpd 訊息傳遞效能測試
    ym24@bio002:~$ mpdringtest 1000
    time for 1000 loops = 1.07995414734 seconds
    
  • 用 mpiexec 執行 cpi 範例程式
    ym24@bio001:~$ mpiexec -n 3 /opt/mpich2/share/mpich2/examples/cpi
    Process 0 of 1 is on bio001
    pi is approximately 3.1415926544231341, Error is 0.0000000008333410
    wall clock time = 0.000295
    Process 0 of 1 is on bio001
    pi is approximately 3.1415926544231341, Error is 0.0000000008333410
    wall clock time = 0.000287
    Process 0 of 1 is on bio001
    pi is approximately 3.1415926544231341, Error is 0.0000000008333410
    wall clock time = 0.000277
    

範例一:test1.c

  • 貼上 test1.c
    ym24@bio001:~$ cat << EOF > test1.c
    #include <stdio.h>
    #include <mpi.h>
    main (int argc, char **argv)
    {
      int rank, size, len;
      char name[MPI_MAX_PROCESSOR_NAME];
      MPI_Init(&argc, &argv);
      int myid, numprocs;
    
      /* 取得 node 總數 */
      MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
      /* 取得本身 node id / rank */
      MPI_Comm_rank(MPI_COMM_WORLD,&myid);
      /* 取得本身 host name */
      MPI_Get_processor_name(name, &len);
      printf("This is machine %d of %d name = %s\n", myid, numprocs, name);
    
      MPI_Finalize();
    }
    EOF
    
  • 用 mpicc 編譯 test1.c
    ym24@bio001:~$ mpicc -o test1 test1.c
    
  • 用 mpiexec 執行 test1 程式
    ym24@bio001:~$ mpiexec -n 1 ./test1
    This is machine 0 of 1 name = bio001
    ym24@bio001:~$ mpiexec -n 12 ./test1
    

範例二:test2.c

  • here is test2.c
    ym24@bio001:~$ cat << EOF > test2.c
    #include <mpi.h>
    #include <stdio.h>
    main(int argc,char **argv) { 
      int n, myrank, numprocs;
      MPI_Status status;
      MPI_Init(&argc,&argv);
      MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
      MPI_Comm_rank(MPI_COMM_WORLD,&myrank);
    
      /* node 0 will send the first message */
      if(myrank == 0) {
        n = myrank;
        MPI_Send(&n, 1, MPI_INT, 1, 99, MPI_COMM_WORLD);
        printf("[Ndde %d]「%d」 >> [Node %d]\n\n", myrank, n, myrank+1);
      }
    
      /* node 1 to node n-2 will send message to the next node */
      if(myrank>0 && myrank<numprocs-1) {
        MPI_Recv(&n, 1, MPI_INT, myrank-1, 99, MPI_COMM_WORLD, &status);
        printf("[Node %d] << 「%d」[Node %d]\n", myrank, n, status.MPI_SOURCE);
        n = myrank; MPI_Send(&n, 1, MPI_INT, myrank+1, 99, MPI_COMM_WORLD);
        printf("[Ndde %d]「%d」 >> [Node %d]\n\n", myrank, n, myrank+1);
      }
    
     /* the final node n-1 will not send any message but receive*/
      if(myrank==numprocs-1) {
        MPI_Recv(&n, 1, MPI_INT, myrank-1, 99, MPI_COMM_WORLD, &status);
        printf("[Node %d] << 「%d」[Node %d]\n", myrank, n, status.MPI_SOURCE);
        }
    
      MPI_Finalize();
    } 
    EOF
    
  • 用 mpicc 編譯 test2.c
    ym24@bio001:~$ mpicc -o test2 test2.c
    
  • 用 mpiexec 執行 test2 程式
    ym24@bio001:~$ mpiexec -n 12 ./test2
    

範例三:test3.c

  • here is test3.c
    ym24@bio001:~$ cat << EOF > test3.c
    /* Program:
     *   每個 node 將訊息傳送給 node 0,由,node 0 統一印出
     * History:
     *   2008-06-12 BETA
     *   2008-06-17 更改顯示方式,並增加註解
     */
    
    #include <stdio.h>
    #include <mpi.h>
    #include <string.h>
    
    main(int argc, char **argv)
    {
      int myrank, i, numprocs;
      char message[20];
      MPI_Status status;
      MPI_Init(&argc, &argv);
      MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
      MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
    
      /* Node 0 will do the following */
      if(myrank == 0)
      {
        /* receive messages from other nodes */
        for(i = 1; i < numprocs; i++)
        {
          MPI_Recv(message, 20, MPI_CHAR, i, 99, MPI_COMM_WORLD, &status);
          printf("[Node 0] << 「%s」[Node %d] \n", message, status.MPI_SOURCE);
        }
      }
    
      /* other Nodes will do the following */
      if(myrank != 0)
      {
        /* send node's rank to Node 0 */
        sprintf(message, "[%d]", myrank);
        MPI_Send(message, 20, MPI_CHAR, 0, 99, MPI_COMM_WORLD);
        printf("[Node %d]「%s」 >> [Node 0]\n", myrank, message);
      }
      MPI_Finalize();
    }
    EOF
    
  • 用 mpicc 編譯 test3.c
    ym24@bio001:~$ mpicc -o test2 test3.c
    
  • 用 mpiexec 執行 test3 程式
    ym24@bio001:~$ mpiexec -n 12 ./test3
    

範例四:test4.c

  • here is test4
    ym24@bio001:~$ cat << EOF > test4.c
    /* Program:
     *   mpich_example 內建範例,計算 pi 。
     * History:
     *   2008-04-11 BETA
     *   2008-06-19 增加可重複輸入欲計算之精準度
     *   2008-06-23 加入 MPI_Barrier 以確保每個 node 在接受 n 後才執行
     */
    
    #include "mpi.h"
    #include <stdio.h>
    #include <math.h>
    #include <time.h>
    
    double f( double );
    double f( double a )
    {
        return (4.0 / (1.0 + a*a));
    }
    
    int main( int argc, char *argv[])
    {
        int done = 0, n, myid, numprocs, i=0;
        double PI25DT = 3.141592653589793238462643;
        double mypi, pi, h, sum, x;
        double startwtime = 0.0, endwtime;
        int  namelen;
        char processor_name[MPI_MAX_PROCESSOR_NAME];
        MPI_Init(&argc,&argv);
        MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
        MPI_Comm_rank(MPI_COMM_WORLD,&myid);
        MPI_Get_processor_name(processor_name,&namelen);
        fprintf(stderr,"Process %d on %s\n",
                myid, processor_name);
        n = 0;
        while (!done)
        {
            /* 由 node 0 將使用者輸入的值送給其它的 node  */
            if (myid == 0)
            {
                printf("Enter the number of intervals: (0 quits) ");
                scanf("%d", &n);
                startwtime = MPI_Wtime();
            }
    
            /* 這非常重要,所有的 node 必需在此同步,才可以收到使用者輸入的 n */
            MPI_Barrier(MPI_COMM_WORLD);
    
            /* 將 n 送給其它的 node  */
            MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
            if (n == 0)
                done = 1;
            else
            {
    
                /* 此為計算 pi 的演算法 */
                h   = 1.0 / (double) n;
                sum = 0.0;
                for (i = myid + 1; i <= n; i += numprocs)
                {
                    x = h * ((double)i - 0.5);
                    sum += f(x);
                }
                mypi = h * sum;
    
                /* 將算完的結果傳給 node 0 加總 */
                MPI_Reduce(&mypi, &pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
                if (myid == 0)
                {
                    printf("pi is approximately %.16f, Error is %.16f\n",
                           pi, fabs(pi - PI25DT));
                    endwtime = MPI_Wtime();
                    printf("wall clock time = %f\n",
                           endwtime-startwtime);
                }
            }
        }
        MPI_Finalize();
        return 0;
    }
    EOF
    
  • 用 mpicc 編譯 test4.c
    ym24@bio001:~$ mpicc -o test2 test4.c
    
  • 用 mpiexec 執行 test4 程式
    ym24@bio001:~$ mpiexec -n 12 ./test4
    
Last modified 15 years ago Last modified on Jul 5, 2009, 3:55:50 PM