.. _mpi_scan: MPI_Scan ======== .. include_body :ref:`MPI_Scan`, :ref:`MPI_Iscan`, :ref:`MPI_Scan_init` - Computes an inclusive scan (partial reduction) .. The following directive tells the man page generation script to generate multiple bindings for this file. .. mpi-bindings: MPI_Scan, MPI_Iscan, MPI_Scan_init .. The following file was automatically generated .. include:: ./bindings/mpi_scan.rst INPUT PARAMETERS ---------------- * ``sendbuf``: Send buffer (choice). * ``count``: Number of elements in input buffer (integer). * ``datatype``: Data type of elements of input buffer (handle). * ``op``: Operation (handle). * ``comm``: Communicator (handle). * ``info``: Info (handle, persistent only) OUTPUT PARAMETERS ----------------- * ``recvbuf``: Receive buffer (choice). * ``request``: Request (handle, non-blocking and persistent only). * ``ierror``: Fortran only: Error status (integer). DESCRIPTION ----------- :ref:`MPI_Scan` is used to perform an inclusive prefix reduction on data distributed across the calling processes. The operation returns, in the *recvbuf* of the process with rank i, the reduction (calculated according to the function *op*) of the values in the *sendbuf*\ s of processes with ranks 0, ..., i (inclusive). The type of operations supported, their semantics, and the constraints on send and receive buffers are as for :ref:`MPI_Reduce`. EXAMPLE ------- This example uses a user-defined operation to produce a segmented scan. A segmented scan takes, as input, a set of values and a set of logicals, where the logicals delineate the various segments of the scan. For example, :: values v1 v2 v3 v4 v5 v6 v7 v8 logicals 0 0 1 1 1 0 0 1 result v1 v1+v2 v3 v3+v4 v3+v4+v5 v6 v6+v7 v8 The result for rank j is thus the sum v(i) + ... + v(j), where i is the lowest rank such that for all ranks n, i <= n <= j, logical(n) = logical(j). The operator that produces this effect is :: [ u ] [ v ] [ w ] [ ] o [ ] = [ ] [ i ] [ j ] [ j ] where ( u + v if i = j w = ( ( v if i != j Note that this is a noncommutative operator. C code that implements it is given below. .. code-block:: c typedef struct { double val; int log; } SegScanPair; /* * the user-defined function */ void segScan(SegScanPair *in, SegScanPair *inout, int *len, MPI_Datatype *dptr) { int i; SegScanPair c; for (i = 0; i < *len; ++i) { if (in->log == inout->log) c.val = in->val + inout->val; else c.val = inout->val; c.log = inout->log; *inout = c; in++; inout++; } } Note that the inout argument to the user-defined function corresponds to the right-hand operand of the operator. When using this operator, we must be careful to specify that it is noncommutative, as in the following: .. code-block:: c int i, base; SeqScanPair a, answer; MPI_Op myOp; MPI_Datatype type[2] = {MPI_DOUBLE, MPI_INT}; MPI_Aint disp[2]; int blocklen[2] = {1, 1}; MPI_Datatype sspair; /* * explain to MPI how type SegScanPair is defined */ MPI_Get_address(a, disp); MPI_Get_address(a.log, disp + 1); base = disp[0]; for (i = 0; i < 2; ++i) disp[i] -= base; MPI_Type_struct(2, blocklen, disp, type, &sspair); MPI_Type_commit(&sspair); /* * create the segmented-scan user-op * noncommutative - set commute (arg 2) to 0 */ MPI_Op_create((MPI_User_function *)segScan, 0, &myOp); ... MPI_Scan(a, answer, 1, sspair, myOp, comm); USE OF IN-PLACE OPTION ---------------------- When the communicator is an intracommunicator, you can perform a scanning operation in place (the output buffer is used as the input buffer). Use the variable MPI_IN_PLACE as the value of the *sendbuf* argument. The input data is taken from the receive buffer and replaced by the output data. NOTES ON COLLECTIVE OPERATIONS ------------------------------ The reduction functions of type MPI_Op do not return an error value. As a result, if the functions detect an error, all they can do is either call :ref:`MPI_Abort` or silently skip the problem. Thus, if the error handler is changed from MPI_ERRORS_ARE_FATAL to something else (e.g., MPI_ERRORS_RETURN), then no error may be indicated. The reason for this is the performance problems in ensuring that all collective routines return the same error value. ERRORS ------ .. include:: ./ERRORS.rst .. seealso:: * :ref:`MPI_Exscan` * :ref:`MPI_Op_create` * :ref:`MPI_Reduce`