MPI_SCATTERV(3)

✨ NAME ✨

Okay bestie, welcome to the Open MPI MPI_SCATTERV(3) page β€” yes, the one and only. It covers MPI_Scatterv, MPI_Iscatterv, and MPI_Scatterv_init, and their whole thing is: scatters a buffer in parts to all tasks in a group. Periodt. πŸ’…


πŸ› οΈ SYNTAX πŸ› οΈ

C Syntax

          #include <mpi.h>

          int MPI_Scatterv(const void *sendbuf, const int sendcounts[], const int displs[],
               MPI_Datatype sendtype, void *recvbuf, int recvcount,
               MPI_Datatype recvtype, int root, MPI_Comm comm)

          int MPI_Iscatterv(const void *sendbuf, const int sendcounts[], const int displs[],
               MPI_Datatype sendtype, void *recvbuf, int recvcount,
               MPI_Datatype recvtype, int root, MPI_Comm comm, MPI_Request *request)

          int MPI_Scatterv_init(const void *sendbuf, const int sendcounts[], const int displs[],
               MPI_Datatype sendtype, void *recvbuf, int recvcount,
               MPI_Datatype recvtype, int root, MPI_Comm comm, MPI_Info info, MPI_Request *request)

Fortran Syntax

          USE MPI
          ! or the older form: INCLUDE 'mpif.h'
          MPI_SCATTERV(SENDBUF, SENDCOUNTS, DISPLS, SENDTYPE, RECVBUF,
                       RECVCOUNT, RECVTYPE, ROOT, COMM, IERROR)
               <type>  SENDBUF(*), RECVBUF(*)
               INTEGER SENDCOUNTS(*), DISPLS(*), SENDTYPE
               INTEGER RECVCOUNT, RECVTYPE, ROOT, COMM, IERROR

          MPI_ISCATTERV(SENDBUF, SENDCOUNTS, DISPLS, SENDTYPE, RECVBUF,
                       RECVCOUNT, RECVTYPE, ROOT, COMM, REQUEST, IERROR)
               <type>  SENDBUF(*), RECVBUF(*)
               INTEGER SENDCOUNTS(*), DISPLS(*), SENDTYPE
               INTEGER RECVCOUNT, RECVTYPE, ROOT, COMM, REQUEST, IERROR

          MPI_SCATTERV_INIT(SENDBUF, SENDCOUNTS, DISPLS, SENDTYPE, RECVBUF,
                       RECVCOUNT, RECVTYPE, ROOT, COMM, INFO, REQUEST, IERROR)
               <type>  SENDBUF(*), RECVBUF(*)
               INTEGER SENDCOUNTS(*), DISPLS(*), SENDTYPE
               INTEGER RECVCOUNT, RECVTYPE, ROOT, COMM, INFO, REQUEST, IERROR

Fortran 2008 Syntax

          USE mpi_f08
          MPI_Scatterv(sendbuf, sendcounts, displs, sendtype, recvbuf, recvcount,
                       recvtype, root, comm, ierror)
               TYPE(*), DIMENSION(..), INTENT(IN) :: sendbuf
               TYPE(*), DIMENSION(..) :: recvbuf
               INTEGER, INTENT(IN) :: sendcounts(*), displs(*), recvcount, root
               TYPE(MPI_Datatype), INTENT(IN) :: sendtype, recvtype
               TYPE(MPI_Comm), INTENT(IN) :: comm
               INTEGER, OPTIONAL, INTENT(OUT) :: ierror

          MPI_Iscatterv(sendbuf, sendcounts, displs, sendtype, recvbuf, recvcount,
                       recvtype, root, comm, request, ierror)
               TYPE(*), DIMENSION(..), INTENT(IN), ASYNCHRONOUS :: sendbuf
               TYPE(*), DIMENSION(..), ASYNCHRONOUS :: recvbuf
               INTEGER, INTENT(IN), ASYNCHRONOUS :: sendcounts(*), displs(*)
               INTEGER, INTENT(IN) :: recvcount, root
               TYPE(MPI_Datatype), INTENT(IN) :: sendtype, recvtype
               TYPE(MPI_Comm), INTENT(IN) :: comm
               TYPE(MPI_Request), INTENT(OUT) :: request
               INTEGER, OPTIONAL, INTENT(OUT) :: ierror

          MPI_scatterv_init(sendbuf, sendcounts, displs, sendtype, recvbuf, recvcount,
                       recvtype, root, comm, info, request, ierror)
               TYPE(*), DIMENSION(..), INTENT(IN), ASYNCHRONOUS :: sendbuf
               TYPE(*), DIMENSION(..), ASYNCHRONOUS :: recvbuf
               INTEGER, INTENT(IN), ASYNCHRONOUS :: sendcounts(*), displs(*)
               INTEGER, INTENT(IN) :: recvcount, root
               TYPE(MPI_Datatype), INTENT(IN) :: sendtype, recvtype
               TYPE(MPI_Comm), INTENT(IN) :: comm
               TYPE(MPI_Info), INTENT(IN) :: info
               TYPE(MPI_Request), INTENT(OUT) :: request
               INTEGER, OPTIONAL, INTENT(OUT) :: ierror

πŸ“₯ INPUT PARAMETERS πŸ“₯

  • sendbuf β€” Address of send buffer (choice, significant only at root). Root gets to be the main character here, obviously. πŸ‘‘
  • sendcounts β€” Integer array (of length group size) specifying the number of elements to send to each processor.
  • displs β€” Integer array (of length group size). Entry i specifies the displacement (relative to sendbuf) from which to take the outgoing data to process i.
  • sendtype β€” Datatype of send buffer elements (handle).
  • recvcount β€” Number of elements in receive buffer (integer).
  • recvtype β€” Datatype of receive buffer elements (handle).
  • root β€” Rank of sending process (integer).
  • comm β€” Communicator (handle).
  • info β€” Info (handle, persistent only).

πŸ“€ OUTPUT PARAMETERS πŸ“€

  • recvbuf β€” Address of receive buffer (choice).
  • request β€” Request (handle, non-blocking only).
  • ierror β€” Fortran only: Error status (integer).

🧠 DESCRIPTION 🧠

MPI_Scatterv is literally the inverse operation to MPI_Gatherv. That's the whole vibe. πŸ¦‹

MPI_Scatterv extends the functionality of MPI_Scatter by allowing a varying count of data to be sent to each process, since sendcounts is now an array. It also allows more flexibility as to where the data is taken from on the root, by providing the new argument, displs. It's giving "scatter, but make it bespoke." ✨

The outcome is as if the root executed n send operations,

          MPI_Send(sendbuf + displs[i] * extent(sendtype),
                   sendcounts[i], sendtype, i, ...);

          // and each process executed a receive,

          MPI_Recv(recvbuf, recvcount, recvtype, root, ...)

The send buffer is ignored for all nonroot processes. Not their moment, okay? πŸ’…

The type signature implied by sendcount[i], sendtype at the root must be equal to the type signature implied by recvcount, recvtype at process i (however, the type maps may be different). This implies that the amount of data sent must be equal to the amount of data received, pairwise between each process and the root. Distinct type maps between sender and receiver are still allowed. No cap, the type maps can differ. 🌈

All arguments to the function are significant on process root, while on other processes, only arguments recvbuf, recvcount, recvtype, root, comm are significant. The arguments root and comm must have identical values on all processes. Fr fr, everybody has to agree on those two. 🀝

🚨 The specification of counts, types, and displacements should not cause any location on the root to be read more than once. That's the rule, bestie β€” do not double-dip on root memory. πŸ’€

Example 1: The reverse of Example 5 in the MPI_Gatherv manpage. We have a varying stride between blocks at sending (root) side, at the receiving side we receive 100 - i elements into the ith column of a 100 x 150 C array at process i.

          MPI_Comm comm;
          int gsize,recvarray[100][150],*rptr;
          int root, *sendbuf, myrank, bufsize, *stride;
          MPI_Datatype rtype;
          int i, *displs, *scounts, offset;
          ...
          MPI_Comm_size( comm, &gsize);
          MPI_Comm_rank( comm, &myrank );

          stride = (int *)malloc(gsize*sizeof(int));
          ...
          /* stride[i] for i = 0 to gsize-1 is set somehow
           * sendbuf comes from elsewhere
           */
          ...
          displs = (int *)malloc(gsize*sizeof(int));
          scounts = (int *)malloc(gsize*sizeof(int));
          offset = 0;
          for (i=0; i<gsize; ++i) {
              displs[i] = offset;
              offset += stride[i];
              scounts[i] = 100 - i;
          }
          /* Create datatype for the column we are receiving
           */
          MPI_Type_vector( 100-myrank, 1, 150, MPI_INT, &rtype);
          MPI_Type_commit( &rtype );
          rptr = &recvarray[0][myrank];
          MPI_Scatterv(sendbuf, scounts, displs, MPI_INT,
                       rptr, 1, rtype, root, comm);

Example 2: The reverse of Example 1 in the MPI_Gather manpage. The root process scatters sets of 100 ints to the other processes, but the sets of 100 are stride ints apart in the sending buffer. Requires use of MPI_Scatterv, where stride >= 100.

          MPI_Comm comm;
          int gsize,*sendbuf;
          int root, rbuf[100], i, *displs, *scounts;

          ...

          MPI_Comm_size(comm, &gsize);
          sendbuf = (int *)malloc(gsize*stride*sizeof(int));
          ...
          displs = (int *)malloc(gsize*sizeof(int));
          scounts = (int *)malloc(gsize*sizeof(int));
          for (i=0; i<gsize; ++i) {
             displs[i] = i*stride;
             scounts[i] = 100;
          }
          MPI_Scatterv(sendbuf, scounts, displs, MPI_INT,
                       rbuf, 100, MPI_INT, root, comm);

πŸ™ˆ USE OF IN-PLACE OPTION πŸ™ˆ

When the communicator is an intracommunicator, you can perform a scatter operation in-place (the output buffer is used as the input buffer). Use the variable MPI_IN_PLACE as the value of the root process recvbuf. In this case, recvcount and recvtype are ignored, and the root process sends no data to itself. Root said "I'm sitting this one out," iconic behavior. 🫢

Note that MPI_IN_PLACE is a special kind of value; it has the same restrictions on its use as MPI_BOTTOM. So treat it with the respect it deserves. πŸ‘‘

Because the in-place option converts the receive buffer into a send-and-receive buffer, a Fortran binding that includes INTENT must mark these as INOUT, not OUT. The Fortran binding gotta be flexible, okay? πŸ’œ


🌍 WHEN COMMUNICATOR IS AN INTER-COMMUNICATOR 🌍

When the communicator is an inter-communicator, the root process in the first group sends data to all processes in the second group. The first group defines the root process. That process uses MPI_ROOT as the value of its root argument. The remaining processes use MPI_PROC_NULL as the value of their root argument. All processes in the second group use the rank of that root process in the first group as the value of their root argument. The receive buffer argument of the root process in the first group must be consistent with the receive buffer argument of the processes in the second group.

πŸ’€ ERRORS πŸ’€

Okay bestie, listen, this part is important so pay attention β€” literally almost all MPI routines return an error value. Like, C routines give it to you as the return result of the function, and Fortran routines put it in the last argument. That's just how it is, no cap. 🫢

Before that error value even comes back to you, the current MPI error handler that's associated with the communication object (think: communicator, window, file β€” you know, the whole squad) gets called. And if there's no communication object associated with the MPI call? Then the call is considered attached to MPI_COMM_SELF and it will call the associated MPI error handler. Simple as that. ✨

Now, when MPI_COMM_SELF is not initialized (i.e., before MPI_Init/MPI_Init_thread, after MPI_Finalize, or when using the Sessions Model exclusively), the error raises the initial error handler. And that initial error handler can be changed by calling MPI_Comm_set_errhandler on MPI_COMM_SELF when you're using the World model, or via the mpi_initial_errhandler CLI argument to mpiexec, or the info key to MPI_Comm_spawn/MPI_Comm_spawn_multiple. Iconic, honestly. πŸ‘‘

And if no other appropriate error handler has been set? Then MPI_ERRORS_RETURN gets called for MPI I/O functions, and MPI_ERRORS_ABORT gets called for all the other MPI functions. That's the default, bestie. πŸŽ€

Open MPI ships with three predefined error handlers you can use, and they're giving very much "pick your fighter":

  • MPI_ERRORS_ARE_FATAL β€” Causes the program to abort all connected MPI processes. Very dramatic, very final. πŸ’€
  • MPI_ERRORS_ABORT β€” An error handler that can be invoked on a communicator, window, file, or session. When called on a communicator, it acts as if MPI_Abort was called on that communicator. If called on a window or file, it acts as if MPI_Abort was called on a communicator containing the group of processes in the corresponding window or file. If called on a session, it aborts only the local process. Ngl, that last one is lowkey considerate. πŸ¦‹
  • MPI_ERRORS_RETURN β€” Returns an error code to the application. Chill. Hands you the receipts. πŸ“

MPI applications can also implement their own error handlers by calling β€” get this β€” 🧚

  • MPI_Comm_create_errhandler then MPI_Comm_set_errhandler
  • MPI_File_create_errhandler then MPI_File_set_errhandler
  • MPI_Session_create_errhandler then MPI_Session_set_errhandler or at MPI_Session_init
  • MPI_Win_create_errhandler then MPI_Win_set_errhandler
Real talk though: note that MPI does not guarantee that an MPI program can continue past an error. So like... don't count on it, bestie. πŸ™ˆ

And if you want the full list of MPI error codes, see the MPI man page. For even more info, see the Error Handling section of the MPI-3.1 standard. The lore is there. πŸ’…


🌈 SEE ALSO 🌈

  • MPI_Gather
  • MPI_Gatherv
  • MPI_Scatter

2003-2026, The Open MPI Community


Okay that's the whole page, bestie β€” you're officially caught up on MPI_SCATTERV(3). This masterpiece dropped on Sep 11, 2026, straight from MPI_SCATTERV(3) itself. Go forth and scatter, you absolute icon. πŸ’–βœ¨πŸŽ€

πŸ“¦ where this page comes from