在英特尔® 至强 融核™ 协处理器系统上使用英特尔® MPI 库

  • 目录

    第 1 章 – 简介

    1.1 – 概述

    1.2 – 兼容性

    第 2 章 – 安装英特尔® MPI 库

    2.1 – 安装英特尔 MPI 库

    2.2 – 准备

    第 3 章 – 编译和运行示例 MPI 程序

    附录

    作者简介

    第1章 简介

    本文旨在帮助用户在包括英特尔® 至强 融核协处理器的开发平台上开始编写代码并运行消息传递接口 (MPI) 应用使用英特尔® MPI

    更具体地说本白皮书中使用的英特尔® MPI 库是面向 Linux* 操作系统的英特尔 MPI 4.1。该英特尔 MPI 库同时支持英特尔® 至强® 处理器和英特尔® 至强 融核协处理器。

    1.1 – 概述

    面向 Linux 操作系统的英特尔 MPI 库是一种基于 ANL* MPICH2* (http://www.mcs.anl.gov/research/projects/mpich2/ ) OSU* MVAPICH2* (http://mvapich.cse.ohio-state.edu/download/mvapich2/ ) 的多结构消息传递库。

    面向 Linux 操作系统的英特尔 MPI 库实施消息传递接口 2.2 (MPI-2.2) 规范。

    它目前支持面向 Linux 操作系统 12.1 版及更高版本的英特尔® C++ 编译器和英特尔® Fortran 编译器。用户可以在 CC++Fortran 77 Fortran 90 中编写其代码。

    1.2 – 兼容性

    面向 Linux 操作系统的英特尔 MPI 库支持大量不同的操作系统其中包括

    Red Hat* Enterprise Linux 64-bit 6.0 内核 2.6.32-71

    Red Hat Enterprise Linux 64-bit 6.1 内核 2.6.32-131

    Red Hat Enterprise Linux 64-bit 6.2 内核 2.6.32-220

    Red Hat Enterprise Linux 64-bit 6.3 内核 2.6.32-279

    SUSE* Linux Enterprise Server 11 SP1 内核 2.6.32.12-0.7-默认

    SUSE Linux Enterprise Server 11 SP2 内核 3.0.13-0.27-默认

    根据在上述平台上运行的英特尔® 众核平台系统软件 (MPSS) 的不同您需要使用正确的编译器面向 Linux 操作系统的英特尔® Composer XE 2013

    请注意面向 Linux 操作系统的英特尔 MPI 4.1 支持多种英特尔® 至强 融核协处理器。

    本文的第一部分介绍了如何在 MPSS 2.1 上安装英特尔 MPI 4.1。第二部分介绍了如何在英特尔® 至强 融核协处理器上运行某些 MPI 示例代码。

    第2章 安装英特尔MPI库

    2.1 – 安装英特尔 MPI

    安装英特尔 MPI 库之前您必须按照相应的步骤安装最新版本的英特尔 C/C++ 编译器和英特尔 Fortran 编译器。本文中使用的版本为 2013

    您可以通过 http://software.intel.com/en-us/linux-tool-suites 购买这些软件开发工具。这些说明假设您获得这些工具后具备英特尔 MPI tar 文件 l_mpi_p_4.1.0.024.tgz

    解包 tar 文件 l_mpi_p_4.1.0.024.tgz

    # tar -xzvf l_mpi_p_4.1.0.024.tgz

    # cd l_mpi_p_4.1.0.024

    # ls

    cd_eject.sh  

    INSTALL.html 

    install.sh   

    license.txt  

    pset         

    Release_Notes.txt

    rpm

    SilentInstallConfigFile.ini

    sshconnectivity.exp

    运行 install.sh 脚本并按照说明操作。对于特定用户安装程序位于安装目录 installation directory $HOME/intel/impi/4.1.0.024 中。对于根用户来说,软件安装在 /opt/intel/impi/4.1.0.024 目录中(假设您使用根权限执行安装)。

    # sudo ./install.sh

    # ls -l /opt/intel/impi/4.1.0.024

    total 208

    -rw-r--r-- 1 root root 28556 Aug 31 07:48 Doc_Index.html

    -rw-r--r-- 1 root root  9398 Aug 31 07:48 README.txt

    lrwxrwxrwx 1 root root     8 Sep 22 17:07 bin -> ia32/bin

    lrwxrwxrwx 1 root root    11 Sep 22 17:07 bin64 -> intel64/bin

    drwxr-xr-x 2 root root  4096 Sep 22 17:07 binding

    drwxr-xr-x 3 root root  4096 Sep 22 17:07 data

    drwxr-xr-x 4 root root  4096 Sep 22 17:07 doc

    lrwxrwxrwx 1 root root     8 Sep 22 17:07 etc -> ia32/etc

    lrwxrwxrwx 1 root root    11 Sep 22 17:07 etc64 -> intel64/etc

    drwxr-xr-x 6 root root  4096 Sep 22 17:07 ia32

    -rw-r--r-- 1 root root   309 Sep 22 17:07 impi.uninstall.config

    lrwxrwxrwx 1 root root    12 Sep 22 17:07 include -> ia32/include

    lrwxrwxrwx 1 root root    15 Sep 22 17:07 include64 -> intel64/include

    drwxr-xr-x 6 root root  4096 Sep 22 17:07 intel64

    lrwxrwxrwx 1 root root     8 Sep 22 17:07 lib -> ia32/lib

    lrwxrwxrwx 1 root root    11 Sep 22 17:07 lib64 -> intel64/lib

    drwxr-xr-x 3 root root  4096 Sep 22 17:07 man

    drwxr-xr-x 6 root root  4096 Sep 22 17:07 mic

    -rw-r--r-- 1 root root 28728 Aug 31 07:48 mpi-rtEULA.txt

    -rw-r--r-- 1 root root   491 Sep  7 04:12 mpi-rtsupport.txt

    -rw-r--r-- 1 root root 28728 Aug 31 07:48 mpiEULA.txt

    -rw-r--r-- 1 root root   283 Sep  7 04:12 mpisupport.txt

    -rw-r--r-- 1 root root  2770 Aug 31 07:48 redist-rt.txt

    -rw-r--r-- 1 root root  1524 Aug 31 07:48 redist.txt

    drwxr-xr-x 2 root root  4096 Sep 22 17:07 test

    -rw-r--r-- 1 root root  7762 Sep 22 15:28 uninstall.log

    -rwxr-xr-x 1 root root 41314 Sep  7 04:12 uninstall.sh

    2.2 – 准备

    在协处理器上首次运行 MPI 应用之前请将 MPI 库复制到该系统的每路英特尔® 至强 融核协处理器上的以下目录。在本例中,我们向两路协处理器发出复制命令。第一路协处理器可通过 IP 地址 172.31.1.1 访问,第二路协处理器的 IP 地址为 172.31.2.1。请注意,所有协处理器的 IP 地址都是唯一的,这是因为它们会被视作另外一个唯一的可寻址设备来对待。您可以根据 mic0 或其 IP 地址来查找第一路协处理器,同样,您可以根据 mic1 或其 IP 地址来查找第二路协处理器。

    # sudo scp /opt/intel/impi/4.1.0.024/mic/bin/mpiexec mic0:/bin/mpiexec

    mpiexec                                                                100% 1061KB   1.0MB/s   00:00   

    # sudo scp /opt/intel/impi/4.1.0.024/mic/bin/pmi_proxy mic0:/bin/pmi_proxy

    pmi_proxy                                                              100%  871KB 871.4KB/s   00:00   

    # sudo scp /opt/intel/impi/4.1.0.024/mic/lib/libmpi.so.4.1 mic0:/lib64/libmpi.so.4

    libmpi.so.4.1                                                          100% 4391KB   4.3MB/s   00:00   

    # sudo scp /opt/intel/impi/4.1.0.024/mic/lib/libmpigf.so.4.1 mic0:/lib64/libmpigf.so.4

    libmpigf.so.4.1                                                        100%  321KB 320.8KB/s   00:00   

    # sudo scp /opt/intel/impi/4.1.0.024/mic/lib/libmpigc4.so.4.1 mic0:/lib64/libmpigc4.so.4

    libmpigc4.so.4.1                                                       100%  175KB 175.2KB/s   00:00   

    # sudo scp /opt/intel/composer_xe_2013.0.079/compiler/lib/mic/libimf.so mic0:/lib64/libimf.so

    libimf.so                                                              100% 2516KB   2.5MB/s   00:01   

    # sudo scp /opt/intel/composer_xe_2013.0.079/compiler/lib/mic/libsvml.so mic0:/lib64/libsvml.so

    libsvml.so                                                             100% 4985KB   4.9MB/s   00:01   

    # sudo scp /opt/intel/composer_xe_2013.0.079/compiler/lib/mic/libintlc.so.5 mic0:/lib64/libintlc.so.5

    libintlc.so.5                                                          100%  128KB 128.1KB/s   00:00

    # sudo scp /opt/intel/impi/4.1.0.024/mic/bin/mpiexec mic1:/bin/mpiexec

    mpiexec                                                                100% 1061KB   1.0MB/s   00:00   

    # sudo scp /opt/intel/impi/4.1.0.024/mic/bin/pmi_proxy mic1:/bin/pmi_proxy

    pmi_proxy                                                              100%  871KB 871.4KB/s   00:00   

    # sudo scp /opt/intel/impi/4.1.0.024/mic/lib/libmpi.so.4.1 mic1:/lib64/libmpi.so.4

    libmpi.so.4.1                                                          100% 4391KB   4.3MB/s   00:00   

    # sudo scp /opt/intel/impi/4.1.0.024/mic/lib/libmpigf.so.4.1 mic1:/lib64/libmpigf.so.4

    libmpigf.so.4.1                                                        100%  321KB 320.8KB/s   00:00   

    # sudo scp /opt/intel/impi/4.1.0.024/mic/lib/libmpigc4.so.4.1 mic1:/lib64/libmpigc4.so.4

    libmpigc4.so.4.1                                                       100%  175KB 175.2KB/s   00:00   

    # sudo scp /opt/intel/composer_xe_2013.0.079/compiler/lib/mic/libimf.so mic1:/lib64/libimf.so

    libimf.so                                                              100% 2516KB   2.5MB/s   00:01   

    # sudo scp /opt/intel/composer_xe_2013.0.079/compiler/lib/mic/libsvml.so mic1:/lib64/libsvml.so

    libsvml.so                                                             100% 4985KB   4.9MB/s   00:01   

    # sudo scp /opt/intel/composer_xe_2013.0.079/compiler/lib/mic/libintlc.so.5 mic1:/lib64/libintlc.so.5

    libintlc.so.5                                                          100%  128KB 128.1KB/s   00:00

     

    您无须手动复制 MPI 只需运行以下脚本即可

    #!/bin/sh

     

    export COPROCESSORS="mic0 mic1"

    export BINDIR="/opt/intel/impi/4.1.0.024/mic/bin"

    export LIBDIR="/opt/intel/impi/4.1.0.024/mic/lib"

    export COMPILERLIB="/opt/intel/composer_xe_2013.0.079/compiler/lib/mic"

     

    for coprocessor in `echo $COPROCESSORS`

    do

       for prog in mpiexec pmi_proxy

       do

          sudo scp $BINDIR/$prog $coprocessor:/bin/$prog

       done

     

       for lib in libmpi.so.4.1 libmpigf.so.4.1 libmpigc4.so.4.1

       do

          sudo scp $LIBDIR/$lib $coprocessor:/lib64/$lib

       done

     

       for lib in libimf.so libsvml.so libintlc.so.5

       do

          sudo scp $COMPILERLIB/$lib $coprocessor:/lib64/$lib

       done

    done

    对于多卡使用环境请以点对点的方式配置 MPSS

    # sudo /sbin/sysctl -w net.ipv4.ip_forward=1

    net.ipv4.ip_forward = 1

    第3章 编译和运行示例MPI程序

    该部分包括了一个使用 C 语言编写的示例 MPI 程序。我们将介绍如何针对主机和英特尔® 至强 融核协处理器编译和运行该程序。

    英特尔® MPI 库支持三种编程模式

    仅协处理器模式在这种本机模式下MPI 列仅位于协处理器中。可通过主机或协处理器启动应用。

    对称模式在该模式下MPI 等级位于主机和协处理器上。

    MPI 卸载模式在该模式下MPI 列仅位于主机上。MPI 列使用英特尔® C/C++ 编译器或英特尔® Fortran 编译器的卸载功能将部分工作负载卸载到协处理器上。

    为便于说明下面的示例展示了如何在对称模式下构建和运行 MPI 应用。

    示例程序使用 Monte Carlo 方法预测 Pi (π) 计算。我们来考虑一个以原点为球心并由一个立方体限制的球体:球体的半径为 r,立方体的边长为 2r。球体和立方体的体积分别为

    坐标系统的第一卦限octant占了球体和立方体体积的八分之一该卦限的体积为

    如果我们在该卦限的球体中以一致、随机的方式生成 Nc 那么根据下面的比例我们预计这 Nc 点将位于球体的体积中

    因此,预计 Pi (π) 的值为:

    其中 Nc 代表第一卦限的立方体部分中生成的点数 Ns 则代表第一卦限的球体部分中的总点数

    在实施中 0进程负责将工作在其它 n 列之间划分。每个列均被分配一组工作,而总和则用于估计 Pi 的值。列 0 x 划分为 n 个相等的段。每列在分配的段中生成 (NC /n) 个点,然后计算球体第一卦限中的点数。


    1 – 每列在第一卦限中处理单独的部分。

    伪代码如下所示

    Rank 0 generate n random seed

    Rank 0 broadcast all random seeds to n rank

    For each rank i [0, n-1]

    receive the corresponding seed

    set num_inside = 0

    For j=0 to Nc / n

    generate a point with coordinates

    x between [i/n, (i+1)/n]

    y between [0, 1]

    z between [0, 1]

                                                  compute the distance d = x^2 + y^2 + z^2

                                                  if distance d <= 1, increment num_inside

                                   Send num_inside back to rank 0

                   Rank 0 set Ns  to the sum of all num_inside

                   Rank 0 compute Pi = 6 * Nc  / Ns

    </pre>

    编译程序montecarlo.c之前你需要针对编译器以及面向英特尔® 至强 融核协处理器的英特尔 MPI 库创建正确的环境设置。

    # source /opt/intel/composer_xe_2013.0.079/bin/compilervars.sh intel64

    # source /opt/intel/impi/4.1.0.024/mic/bin/mpivars.sh

    针对协处理器构建应用 montecarlo.mic

    # mpiicc –mmic montecarlo.c -o montecarlo.mic

    要构建在主机上运行的应用你需要针对英特尔® 64 英特尔 MPI 库创建环境设置。

    # source /opt/intel/impi/4.1.0.024/intel64/bin/mpivars.sh

    构建面向主机的应用

    # mpiicc montecarlo.c -o montecarlo.host

    使用 scp 命令将应用 montecarlo.mic 上传到协处理器上的 /tmp目录。在本例中,我们向两路协处理器发出复制命令。

    # sudo scp ./montecarlo.mic mic0:/tmp/montecarlo.mic

    montecarlo.mic                                100%   15KB  15.5KB/s   00:00

    # sudo scp ./montecarlo.mic mic1:/tmp/montecarlo.mic

    montecarlo.mic                                100%   15KB  15.5KB/s   00:00

    启用主机和协处理器之间的 MPI 通信

    # export I_MPI_MIC=enable

    使用命令 mpirun 来启动应用。此外标记 –n 指定了 MPI 进程的数量标记 –host 指定了设备名称

    # mpirun –n <# of processes> -host <hostname> <application>

    我们可以在多台主机上运行应用具体方法是使用 “:”将其隔开。第一个 MPI (rank 0) 总是在命令的第一个部分启动:

    # mpirun –n <# of processes> -host <hostname1> <application> : –n <# of processes> -host <hostname2> <application>

    这将在 hostname1 上启动 rank 0

    现在在主机上运行应用。下面所示的 mpirun 命令启动带有两个列主机上3 个列协处理器 MIC0 5 个列协处理器 MIC1 的应用

    # mpirun -n 2 -host knightscorner1 ./montecarlo.host \

    : -n 3 -host mic0 /tmp/montecarlo.mic \

    : -n 5 -host mic1 /tmp/montecarlo.mic

    Hello world: rank 0 of 10 running on knightscorner1

    Hello world: rank 1 of 10 running on knightscorner1

    Hello world: rank 2 of 10 running on knightscorner1-mic0

    Hello world: rank 3 of 10 running on knightscorner1-mic0

    Hello world: rank 4 of 10 running on knightscorner1-mic0

    Hello world: rank 5 of 10 running on knightscorner1-mic1

    Hello world: rank 6 of 10 running on knightscorner1-mic1

    Hello world: rank 7 of 10 running on knightscorner1-mic1

    Hello world: rank 8 of 10 running on knightscorner1-mic1

    Hello world: rank 9 of 10 running on knightscorner1-mic1

    Elapsed time from rank 0:      14.79 (sec)

    Elapsed time from rank 1:      14.90 (sec)

    Elapsed time from rank 2:     219.87 (sec)

    Elapsed time from rank 3:     218.24 (sec)

    Elapsed time from rank 4:     218.29 (sec)

    Elapsed time from rank 5:     218.94 (sec)

    Elapsed time from rank 6:     218.74 (sec)

    Elapsed time from rank 7:     218.42 (sec)

    Elapsed time from rank 8:     217.93 (sec)

    Elapsed time from rank 9:     217.35 (sec)

    Out of 4294967295 points, there are 2248861895 points inside the sphere => pi=  3.141623973846

    在对称模式下一种简单的方法是根据 I_MPI_MIC_POSTFIX 环境变量针对 mpirun 命令使用 –machinefile 参数。在这种情况下,请确保所有可执行文件均位于主机以及 MIC0 MIC1 卡的相同位置。

    在卡上运行时I_MPI_MIC_POSTFIX 环境变量会命令库添加.mic 后缀因为这里的可执行文件被称为 montecarlo.mic

    # export I_MPI_MIC_POSTFIX=.mic

    现在请在您的主机文件中设置列映射使用 <host>:<#_ranks> 格式):

    # cat hosts_file

    knightscorner1:2

    mic0:3

    mic1:5

    运行您的可执行文件

    # cp ./montecarlo.host /tmp/montecarlo

    # mpirun -machinefile hosts_file /tmp/montecarlo

    该语法有一项优势当决定更改列数或需要添加更多的卡时只需编辑 hosts_file 即可。

    或者您也可以在主机上启动仅在协处理器 mic0 mic1上运行的应用

    # mpirun -n 3 -host mic0 /tmp/montecarlo.mic : -n 5 -host mic1 \ /tmp/montecarlo.mic

    Hello world: rank 0 of 8 running on knightscorner1-mic0

    Hello world: rank 1 of 8 running on knightscorner1-mic0

    Hello world: rank 2 of 8 running on knightscorner1-mic0

    Hello world: rank 3 of 8 running on knightscorner1-mic1

    Hello world: rank 4 of 8 running on knightscorner1-mic1

    Hello world: rank 5 of 8 running on knightscorner1-mic1

    Hello world: rank 6 of 8 running on knightscorner1-mic1

    Hello world: rank 7 of 8 running on knightscorner1-mic1

    Elapsed time from rank 0:     273.71 (sec)

    Elapsed time from rank 1:     273.20 (sec)

    Elapsed time from rank 2:     273.66 (sec)

    Elapsed time from rank 3:     273.84 (sec)

    Elapsed time from rank 4:     273.53 (sec)

    Elapsed time from rank 5:     273.24 (sec)

    Elapsed time from rank 6:     272.59 (sec)

    Elapsed time from rank 7:     271.64 (sec)

    Out of 4294967295 points, there are 2248861679 points inside the sphere => pi= 3.141623497009

    另外您也可以向协处理器 mic0 发出 ssh 命令并启动那里的应用

    # ssh mic0

    # mpiexec -n 3 /tmp/montecarlo.mic

    Hello world: rank 0 of 3 running on knightscorner1-mic0

    Hello world: rank 1 of 3 running on knightscorner1-mic0

    Hello world: rank 2 of 3 running on knightscorner1-mic0

    Elapsed time from rank 0:     732.09 (sec)

    Elapsed time from rank 1:     727.86 (sec)

    Elapsed time from rank 2:     724.82 (sec)

    Out of 4294967295 points, there are 2248845386 points inside the sphere => pi=  3.141600608826

    附录

    示例 MPI 程序的代码如下所示。

    001 /*
    002 // Copyright 2003-2012 Intel Corporation. All Rights Reserved.
    003 //
    004 // The source code contained or described herein and all documents related
    005 // to the source code ("Material") are owned by Intel Corporation or its
    006 // suppliers or licensors.  Title to the Material remains with Intel Corporation
    007 // or its suppliers and licensors.  The Material is protected by worldwide
    008 // copyright and trade secret laws and treaty provisions.  No part of the
    009 // Material may be used, copied, reproduced, modified, published, uploaded,
    010 // posted, transmitted, distributed, or disclosed in any way without Intel's
    011 // prior express written permission.
    012 //
    013 // No license under any patent, copyright, trade secret or other intellectual
    014 // property right is granted to or conferred upon you by disclosure or delivery
    015 // of the Materials, either expressly, by implication, inducement, estoppel
    016 // or otherwise.  Any license under such intellectual property rights must
    017 // be express and approved by Intel in writing.
    018  
    019  
    020 #******************************************************************************
    021 # Content: (version 0.5)
    022 #      Based on a Monto Carlo method, this MPI sample code uses volumes to
    023 #      estimate the number PI.
    024 #     
    025 #*****************************************************************************/
    026 #include <stdlib.h>
    027 #include <stdio.h>
    028 #include <math.h>
    029 #include <time.h>
    030 #include <math.h>
    031  
    032 #include "mpi.h"
    033  
    034 #define MASTER 0
    035 #define TAG_HELLO 4
    036 #define TAG_TEST 5
    037 #define TAG_TIME 6
    038  
    039 int main(int argc, char *argv[])
    040 {
    041   int i, id, remote_id, num_procs;
    042     
    043   MPI_Status stat;
    044   int namelen;
    045   char name[MPI_MAX_PROCESSOR_NAME];
    046  
    047   // Start MPI.
    048   if (MPI_Init (&argc, &argv) != MPI_SUCCESS)
    049     {
    050       printf ("Failed to initialize MPIn");
    051       return (-1);
    052     }
    053   // Create the communicator, and retrieve the number of processes.
    054   MPI_Comm_size (MPI_COMM_WORLD, &num_procs);
    055  
    056   // Determine the rank of the process.
    057   MPI_Comm_rank (MPI_COMM_WORLD, &id);
    058  
    059   // Get machine name
    060   MPI_Get_processor_name (name, &namelen);
    061    
    062   if (id == MASTER)
    063     {
    064       printf ("Hello world: rank %d of %d running on %sn", id, num_procs, name);
    065  
    066       for (i = 1; i<num_procs; i++)
    067     {  
    068       MPI_Recv (&remote_id, 1, MPI_INT, i, TAG_HELLO, MPI_COMM_WORLD, &stat);  
    069       MPI_Recv (&num_procs, 1, MPI_INT, i, TAG_HELLO, MPI_COMM_WORLD, &stat);      
    070       MPI_Recv (&namelen, 1, MPI_INT, i, TAG_HELLO, MPI_COMM_WORLD, &stat);        
    071       MPI_Recv (name, namelen+1, MPI_CHAR, i, TAG_HELLO, MPI_COMM_WORLD, &stat);
    072              
    073       printf ("Hello world: rank %d of %d running on %sn", remote_id, num_procs, name);
    074     }
    075 }
    076   else  
    077     {      
    078       MPI_Send (&id, 1, MPI_INT, MASTER, TAG_HELLO, MPI_COMM_WORLD);
    079       MPI_Send (&num_procs, 1, MPI_INT, MASTER, TAG_HELLO, MPI_COMM_WORLD);
    080       MPI_Send (&namelen, 1, MPI_INT, MASTER, TAG_HELLO, MPI_COMM_WORLD);
    081       MPI_Send (name, namelen+1, MPI_CHAR, MASTER, TAG_HELLO, MPI_COMM_WORLD);
    082 }
    083  
    084    // Rank 0 distributes seek randomly to all processes.
    085   double startprocess, endprocess;
    086  
    087   int distributed_seed = 0;
    088   int *buff;
    089  
    090   buff = (int *)malloc(num_procs * sizeof(int));
    091      
    092   unsigned int MAX_NUM_POINTS = pow (2,32) - 1;
    093   unsigned int num_local_points = MAX_NUM_POINTS / num_procs;
    094  
    095   if (id == MASTER)
    096     {        
    097       srand (time(NULL));
    098    
    099       for (i=0; i<num_procs; i++)   
    100     {          
    101       distributed_seed = rand();
    102       buff[i] = distributed_seed;
    103     }
    104     }
    105  
    106   // Broadcast the seed to all processes
    107   MPI_Bcast(buff, num_procs, MPI_INT, MASTER, MPI_COMM_WORLD);
    108  
    109   // At this point, every process (including rank 0) has a different seed. Using their seed,
    110   // each process generates N points randomly in the interval [1/n, 1, 1]
    111   startprocess = MPI_Wtime();
    112  
    113   srand (buff[id]);
    114  
    115   unsigned int point = 0;
    116   unsigned int rand_MAX = 128000;
    117   float p_x, p_y, p_z;
    118   float temp, temp2, pi;
    119   double result;
    120   unsigned int inside = 0, total_inside = 0;
    121  
    122   for (point=0; point<num_local_points; point++)
    123     {
    124       temp = (rand() % (rand_MAX+1));
    125       p_x = temp / rand_MAX;
    126       p_x = p_x / num_procs;
    127        
    128       temp2 = (float)id / num_procs;    // id belongs to 0, num_procs-1
    129       p_x += temp2;
    130        
    131       temp = (rand() % (rand_MAX+1));
    132       p_y = temp / rand_MAX;
    133        
    134       temp = (rand() % (rand_MAX+1));
    135       p_z = temp / rand_MAX;
    136  
    137       // Compute the number of points residing inside of the 1/8 of the sphere
    138       result = p_x * p_x + p_y * p_y + p_z * p_z;
    139  
    140       if (result <= 1)
    141       {
    142         inside++;
    143       }
    144     }
    145  
    146   double elapsed = MPI_Wtime() - startprocess;
    147  
    148   MPI_Reduce (&inside, &total_inside, 1, MPI_UNSIGNED, MPI_SUM, MASTER, MPI_COMM_WORLD);
    149  
    150  
    151 #if DEBUG
    152   printf ("rank %d counts %u points inside the spheren", id, inside);
    153 #endif
    154   if (id == MASTER)
    155     {
    156       double timeprocess[num_procs];
    157  
    158       timeprocess[MASTER] = elapsed;
    159       printf("Elapsed time from rank %d: %10.2f (sec) n", MASTER, timeprocess[MASTER]);
    160  
    161       for (i=1; i<num_procs; i++)
    162     {
    163       // Rank 0 waits for elapsed time value
    164       MPI_Recv (&timeprocess[i], 1, MPI_DOUBLE, i, TAG_TIME, MPI_COMM_WORLD, &stat);
    165       printf("Elapsed time from rank %d: %10.2f (sec) n", i, timeprocess[i]);
    166     }
    167  
    168       temp = 6 * (float)total_inside;
    169       pi = temp / MAX_NUM_POINTS;  
    170       printf ( "Out of %u points, there are %u points inside the sphere => pi=%16.12fn", MAX_NUM_POINTS, total_inside, pi);
    171     }
    172   else
    173     {
    174       // Send back the processing time (in second)
    175       MPI_Send (&elapsed, 1, MPI_DOUBLE, MASTER, TAG_TIME, MPI_COMM_WORLD);
    176     }
    177  
    178   free(buff);
    179  
    180   // Terminate MPI.
    181   MPI_Finalize();
    182    
    183   return 0;
    184 }

作者简介

Loc Q Nguyen 获得了达拉斯大学 MBA 学位、麦吉尔大学电子工程专业硕士学位以及蒙特利尔理工学院电子工程专业学士学位。他目前在英特尔公司软件及服务事业部担任软件工程师。他研究的领域包括计算网络、计算机图形和并行处理。

Para obter mais informações sobre otimizações de compiladores, consulte Aviso sobre otimizações.