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). entryispecifies the displacement (relative tosendbuf) from which to take the outgoing data to processi. 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 thatMPI_IN_PLACEis a special kind of value; it has the same restrictions on its use asMPI_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_errhandleronMPI_COMM_SELFwhen you're using the World model, or - use the
mpi_initial_errhandlerCLI argument tompiexec, 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_RETURNgets called for MPI I/O functionsMPI_ERRORS_ABORTgets 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_Abortwas called on that communicator - when called on a window or file, it acts as if
MPI_Abortwas 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 π«Ά
- when called on a communicator, it acts as if
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_errhandlerthenMPI_Comm_set_errhandlerMPI_File_create_errhandlerthenMPI_File_set_errhandlerMPI_Session_create_errhandlerthenMPI_Session_set_errhandlerβ or atMPI_Session_initMPI_Win_create_errhandlerthenMPI_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_GatherMPI_GathervMPI_Scatter
π COPYRIGHT π
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
- ubuntu stonking: openmpi-doc 5.0.10-6 Β· other
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms