MPI_SCATTERV(3)

MPI_SCATTERV πŸ’…βœ¨

okay bestie, welcome to the Open MPI manual page for MPI_SCATTERV and its two chaotic siblings. sit down, grab a strawberry drink πŸ“, and let's get into it.

MPI_Scatterv, MPI_Iscatterv, MPI_Scatterv_init β€” scatters a buffer in parts to all tasks in a group. yes literally handing out lil pieces of your data to everybody. it's giving ✨oprah energy✨ but for buffers.


🌸 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 πŸŽ€

the stuff you gotta feed it, bestie:

  • sendbuf β€” address of the send buffer (choice, significant only at root). so only the root girlie actually cares about this one πŸ’…
  • sendcounts β€” integer array (of length group size) specifying the number of elements to send to each processor. yes every single process gets its own lil number.
  • 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. it's the lil "where do i grab from" map πŸ—ΊοΈ
  • 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). the main character of this operation fr πŸ‘‘
  • comm β€” communicator (handle).
  • info β€” info (handle, persistent only).

🌈 OUTPUT PARAMETERS 🌈

what it hands back to you:

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

πŸ’– DESCRIPTION πŸ’–

okay so. MPI_Scatterv is the inverse operation to MPI_Gatherv.

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. no more "everyone gets the same amount" β€” it's giving personalized portions. it also allows more flexibility as to where the data is taken from on the root, by providing the new argument, displs. so like, the root can grab from wherever it wants in sendbuf. slay.

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, ...)
ngl the send buffer is ignored for all nonroot processes. don't worry about it if you're not the root bestie.

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. so like, the vibe of the data has to match, even if the layout doesn't πŸ’€

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. no cap.

🚨 the specification of counts, types, and displacements should not cause any location on the root to be read more than once. fr fr, don't do it.

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. self-care, honestly 🫢

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 same energy.

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. periodt.


🧚 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. it's a whole lil relay race πŸƒβ€β™€οΈπŸ’¨

😭 ERRORS 😭

okay bestie, so here's the tea on errors β€” and no, you can't just ignore them πŸ’€

Almost every single MPI routine returns an error value. C routines hand it back as the return result of the function, and Fortran routines drop it in the last argument. Three cheers for consistency πŸŽ‰

Before that error value comes back to you, something else happens first, and you need to know about it. πŸ‘€

The current MPI error handler associated with the communication object (think: communicator, window, file) gets called. That's right β€” the error handler runs before you even see the value. πŸ™ˆ

If no communication object is associated with the MPI call, then the call is considered attached to MPI_COMM_SELF and it'll call the associated MPI error handler. Simple enough, right?

But here's where it gets spicy 🌢️ β€” when MPI_COMM_SELF is not initialized, the error raises the initial error handler instead. And when exactly is it not initialized? Let me count the ways:

  • before MPI_Init / MPI_Init_thread
  • after MPI_Finalize
  • or when you're using the Sessions Model exclusively

Good news though β€” you can change that initial error handler πŸ’…:

  • call MPI_Comm_set_errhandler on MPI_COMM_SELF when you're using the World model, or
  • use the mpi_initial_errhandler CLI argument to mpiexec, or
  • use the info key to MPI_Comm_spawn / MPI_Comm_spawn_multiple

And if no other appropriate error handler has been set? Then the defaults kick in, and they're different depending on what you're doing:

  • MPI_ERRORS_RETURN gets called for MPI I/O functions
  • MPI_ERRORS_ABORT gets called for all other MPI functions

🌸 The three predefined error handlers Open MPI ships with 🌸

These are already in the box, no assembly required:

  • MPI_ERRORS_ARE_FATAL β€” causes the program to abort all connected MPI processes. Everyone's going down together, bestie 😭
  • 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
    • when 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
    • when called on a session, it aborts only the local process 🫢
  • MPI_ERRORS_RETURN β€” returns an error code to the application. that's it, that's the whole vibe ✨

πŸ¦‹ DIY error handlers, because you're that girl πŸ¦‹

MPI applications can also implement their own error handlers. Just pair up the create + set calls:

  • 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

look at you, custom error handling, main character energy πŸ‘‘


⚠️ IMPORTANT, no cap: note that MPI does not guarantee that an MPI program can continue past an error. So don't be out here assuming you'll just recover and keep vibing. Sometimes it's over. πŸ’€

If you want the full list of MPI error codes, see the MPI man page. And for the deep lore, see the Error Handling section of the MPI-3.1 standard. πŸ“š


πŸ‘‘ SEE ALSO πŸ‘‘

  • MPI_Gather
  • MPI_Gatherv
  • MPI_Scatter

2003-2026, The Open MPI Community


and that's the whole page bestie, you made it to the end πŸŽ€ this lil manual drop is from Sep 10, 2026, brought to you by the Open MPI docs, MPI_SCATTERV(3) β€” go forth and scatter those buffers correctly, fr fr πŸ¦‹βœ¨πŸ’œ

πŸ“¦ where this page comes from