17.2.294. MPI_Reduce_local

MPI_Reduce_local — 执行本地归约操作

17.2.294.1. 语法

17.2.294.1.1. C语法

#include <mpi.h>

int MPI_Reduce_local(const void *inbuf, void *inoutbuf, int count,
     MPI_Datatype datatype, MPI_Op op)

17.2.294.1.2. Fortran语法

USE MPI
! or the older form: INCLUDE 'mpif.h'
MPI_REDUCE_LOCAL(INBUF, INOUTBUF, COUNT, DATATYPE, OP, IERROR)
     <type>  INBUF(*), INOUTBUF(*)
     INTEGER COUNT, DATATYPE, OP, IERROR

17.2.294.1.3. Fortran 2008 语法

USE mpi_f08
MPI_Reduce_local(inbuf, inoutbuf, count, datatype, op, ierror)
     TYPE(*), DIMENSION(..), INTENT(IN) :: inbuf
     TYPE(*), DIMENSION(..) :: inoutbuf
     INTEGER, INTENT(IN) :: count
     TYPE(MPI_Datatype), INTENT(IN) :: datatype
     TYPE(MPI_Op), INTENT(IN) :: op
     INTEGER, OPTIONAL, INTENT(OUT) :: ierror

17.2.294.2. 输入参数

  • inbuf: 输入缓冲区的地址(选项)。

  • count: 输入缓冲区中的元素数量(整数)。

  • datatype: 输入缓冲区元素的数据类型(句柄)。

  • op: 归约操作(句柄)。

17.2.294.3. 输出参数

  • inoutbuf: 输入/输出缓冲区的地址(选项)。

  • ierror: 仅限Fortran:错误状态(整数)。

17.2.294.4. 描述

全局归约函数(MPI_Reduce_localMPI_Op_createMPI_Op_freeMPI_Allreduce、MPI_Reduce_local_scatter、MPI_Scan)用于在 组内所有成员之间执行全局归约操作(如求和、最大值、逻辑与等)。归约操作可以是预定义操作列表中的一种, 也可以是用户自定义操作。全局归约函数有多种形式:将归约结果返回给单个节点的reduce操作、 将结果返回给所有节点的all-reduce操作,以及扫描(并行前缀)操作。此外, reduce-scatter操作结合了reduce和scatter操作的功能。

MPI_Reduce_local 将本地进程输入缓冲区和输入/输出缓冲区中的元素通过操作op进行组合,并将结果返回到inout/output缓冲区中。输入缓冲区由参数inbuf、count和datatype定义;输出缓冲区由参数inoutbuf、count和datatype定义;两者具有相同数量的元素和相同类型。该例程是一个本地调用。进程可以提供一个元素或一个元素序列,在这种情况下,组合操作会对序列中的每个条目逐个执行。例如,如果操作是MPI_MAX且输入缓冲区包含两个浮点数元素(count = 2且datatype = MPI_FLOAT),那么inoutbuf(1) = 全局最大值(inbuf(1))且inoutbuf(2) = 全局最大值(inbuf(2))。

17.2.294.5. 原地选项的使用

MPI_Reduce_local中不允许使用MPI_IN_PLACE。

17.2.294.6. 预定义的归约操作

MPI提供的预定义操作集如下所示(预定义归约操作)。该部分还列举了每个操作可应用的数据类型。此外,用户可以定义自己的操作,这些操作可以被重载以处理多种数据类型,包括基本类型和派生类型。关于用户自定义操作的详细说明,请参阅相关手册页(参见MPI_Op_create和MPI_Op_free)。

操作op始终被假定为具有结合性。所有预定义的操作也被假定为具有交换性。用户可以定义被假定为具有结合性但不具有交换性的操作。归约操作的"规范"执行顺序由组中进程的等级决定。然而,实现可以利用结合性,或结合性和交换性来改变执行顺序。对于非严格结合和交换的操作(如浮点加法),这可能会改变归约的结果。

预定义运算符仅适用于下面列出的MPI类型(预定义归约操作,以及下方的MINLOC和MAXLOC部分)。用户自定义运算符可以操作通用的派生数据类型。在这种情况下,归约操作应用的每个参数都是由此类数据类型描述的一个元素,可能包含多个基本值。MPI标准第4.9.4节"用户自定义操作"对此有进一步说明。

以下预定义操作用于MPI_Reduce_local及相关函数MPI_AllreduceMPI_Reduce_scatterMPI_Scan。这些操作通过在op参数中指定以下内容来调用:

Name                Meaning
---------           --------------------
MPI_MAX             maximum
MPI_MIN             minimum
MPI_SUM             sum
MPI_PROD            product
MPI_LAND            logical and
MPI_BAND            bit-wise and
MPI_LOR             logical or
MPI_BOR             bit-wise or
MPI_LXOR            logical xor
MPI_BXOR            bit-wise xor
MPI_MAXLOC          max value and location
MPI_MINLOC          min value and location

MPI_MINLOC和MPI_MAXLOC这两个操作将在下文中单独讨论(MINLOC和MAXLOC)。对于其他预定义操作,我们下面列举了允许的op和datatype参数组合。首先,按照以下方式定义MPI基本数据类型组:

C integer:            MPI_INT, MPI_LONG, MPI_SHORT,
                      MPI_UNSIGNED_SHORT, MPI_UNSIGNED,
                      MPI_UNSIGNED_LONG
Fortran integer:      MPI_INTEGER
Floating-point:       MPI_FLOAT, MPI_DOUBLE, MPI_REAL,
                      MPI_DOUBLE_PRECISION, MPI_LONG_DOUBLE
Logical:              MPI_LOGICAL
Complex:              MPI_COMPLEX
Byte:                 MPI_BYTE

现在,每个选项的有效数据类型如下所示。

Op                              Allowed Types
----------------         ---------------------------
MPI_MAX, MPI_MIN                C integer, Fortran integer,
                                        floating-point

MPI_SUM, MPI_PROD               C integer, Fortran integer,
                                        floating-point, complex

MPI_LAND, MPI_LOR,              C integer, logical
MPI_LXOR

MPI_BAND, MPI_BOR,              C integer, Fortran integer, byte
MPI_BXOR

17.2.294.7. MINLOC 与 MAXLOC

操作符MPI_MINLOC用于计算全局最小值及其对应的索引。类似地,MPI_MAXLOC用于计算全局最大值及其索引。这些操作的一个应用场景是计算全局最小(最大)值以及包含该值的进程的排名。

定义MPI_MAXLOC的操作是

         ( u )    (  v )      ( w )
         (   )  o (    )   =  (   )
         ( i )    (  j )      ( k )

where

    w = max(u, v)

and

         ( i            if u > v
         (
   k   = ( min(i, j)    if u = v
         (
         (  j           if u < v)

MPI_MINLOC的定义方式类似:

         ( u )    (  v )      ( w )
         (   )  o (    )   =  (   )
         ( i )    (  j )      ( k )

where

    w = min(u, v)

and

         ( i            if u < v
         (
   k   = ( min(i, j)    if u = v
         (
         (  j           if u > v)

这两种操作都具有结合性和交换性。需要注意的是,如果对一系列(u(0), 0), (u(1), 1), ..., (u(n-1), n-1)这样的数值对应用MPI_MAXLOC进行归约操作,返回的结果将是(u, r),其中u= max(i) u(i),而r是该序列中第一个全局最大值的索引。因此,如果每个进程提供一个值及其在组内的排名,那么使用op = MPI_MAXLOC的归约操作将返回最大值以及第一个具有该值的进程的排名。类似地,MPI_MINLOC可用于返回最小值及其索引。更一般地说,MPI_MINLOC计算的是字典序最小值,其中元素根据每对数值的第一个分量排序,当第一个分量相同时则根据第二个分量决定顺序。

归约操作被定义为对由值和索引组成的参数对进行操作。对于Fortran和C语言,都提供了描述这种参数对的类型。这种参数可能具有混合类型的特性在Fortran中会带来问题。针对Fortran,通过让MPI提供的类型由与值相同类型的对组成,并将索引强制转换为相同类型,从而规避了这个问题。而在C语言中,MPI提供的参数对类型具有不同的类型,且索引是一个整型。

为了在归约操作中使用MPI_MINLOC和MPI_MAXLOC,必须提供一个表示值-索引对的数据类型参数。OpenMPI提供了九种这样的预定义数据类型。MPI_MAXLOC和MPI_MINLOC操作可与以下每种数据类型配合使用:

Fortran:
Name                     Description
MPI_2REAL                pair of REALs
MPI_2DOUBLE_PRECISION    pair of DOUBLE-PRECISION variables
MPI_2INTEGER             pair of INTEGERs

C:
Name                     Description
MPI_FLOAT_INT            float and int
MPI_DOUBLE_INT           double and int
MPI_LONG_INT             long and int
MPI_2INT                 pair of ints
MPI_SHORT_INT            short and int
MPI_LONG_DOUBLE_INT      long double and int

数据类型 MPI_2REAL 等同于:

call MPI_TYPE_CONTIGUOUS(2, MPI_REAL, MPI_2REAL)

类似的声明适用于MPI_2INTEGER、MPI_2DOUBLE_PRECISION和MPI_2INT。

MPI_FLOAT_INT 数据类型相当于通过以下指令序列定义的。

::.. 代码块:: c

type[0] = MPI_FLOAT type[1] = MPI_INT disp[0] = 0 disp[1] = sizeof(float) block[0] = 1 block[1] = 1 MPI_TYPE_STRUCT(2, block, disp, type, MPI_FLOAT_INT)

类似的声明也适用于MPI_LONG_INT和MPI_DOUBLE_INT。

所有MPI对象(例如MPI_Datatype、MPI_Comm)在Fortran中都是INTEGER类型。

17.2.294.8. 关于集合操作的注意事项

归约操作符(MPI_Op)不会返回错误值。因此,如果函数检测到错误,它们只能选择调用MPI_Abort或静默跳过该问题。因此,如果您将错误处理程序从MPI_ERRORS_ARE_FATAL更改为其他选项,例如MPI_ERRORS_RETURN,则可能不会指示任何错误。

原因在于确保所有集合例程返回相同错误值时存在的性能问题。

17.2.294.9. 错误

几乎所有MPI例程都会返回一个错误值;C语言例程通过函数返回值返回,Fortran例程则通过最后一个参数返回。

在返回错误值之前,会调用与通信对象(如通信器、窗口、文件)关联的当前MPI错误处理程序。如果MPI调用未关联任何通信对象,则该调用被视为附加到MPI_COMM_SELF,并将调用关联的MPI错误处理程序。当MPI_COMM_SELF未初始化时(即在MPI_Init/MPI_Init_thread之前、MPI_Finalize之后,或仅使用会话模型时),错误会触发初始错误处理程序。初始错误处理程序可通过在使用世界模型时调用MPI_Comm_set_errhandler来修改MPI_COMM_SELF,或通过mpiexec的mpi_initial_errhandler命令行参数,或MPI_Comm_spawn/MPI_Comm_spawn_multiple的info键来设置。如果未设置其他适当的错误处理程序,则MPI I/O函数将调用MPI_ERRORS_RETURN错误处理程序,而其他所有MPI函数将调用MPI_ERRORS_ABORT错误处理程序。

Open MPI 包含三个可使用的预定义错误处理器:

  • MPI_ERRORS_ARE_FATAL 导致程序中止所有连接的MPI进程。

  • MPI_ERRORS_ABORT 一个可在通信器、窗口、文件或会话上调用的错误处理程序。当在通信器上调用时,其行为类似于在该通信器上调用MPI_Abort。如果在窗口或文件上调用,则行为类似于在包含对应窗口或文件中进程组的通信器上调用MPI_Abort。如果在会话上调用,则仅中止本地进程。

  • MPI_ERRORS_RETURN 向应用程序返回一个错误代码。

MPI应用程序也可以通过调用以下方式实现自己的错误处理程序:

请注意,MPI不保证MPI程序在出现错误后能够继续运行。

查看MPI手册页获取完整的MPI错误代码列表。

有关更多信息,请参阅MPI-3.1标准中的错误处理部分。