MPI_NEIGHBOR_ALLTOALLW_INIT(3)
π MPI_NEIGHBOR_ALLTOALLW_INIT π
okay bestie, gather round β this is the Open MPI manual page for MPI_NEIGHBOR_ALLTOALLW_INIT(3), and it's a whole family of functions, not just one. We're talking the β¨ trio β¨:
MPI_Neighbor_alltoallwMPI_Ineighbor_alltoallwMPI_Neighbor_alltoallw_init
πΈ NAME πΈ
MPI_Neighbor_alltoallw, MPI_Ineighbor_alltoallw, MPI_Neighbor_alltoallw_init β all processes send data of different types to, and receive data of different types from, all processes. no cap, it's giving "everyone trades custom-shaped gossip with everyone" π
β¨ SYNTAX β¨
π C Syntax
#include <mpi.h>
int MPI_Neighbor_alltoallw(const void *sendbuf, const int sendcounts[],
const MPI_Aint sdispls[], const MPI_Datatype sendtypes[],
void *recvbuf, const int recvcounts[], const MPI_Aint rdispls[],
const MPI_Datatype recvtypes[], MPI_Comm comm)
int MPI_Ineighbor_alltoallw(const void *sendbuf, const int sendcounts[],
const MPI_Aint sdispls[], const MPI_Datatype sendtypes[],
void *recvbuf, const int recvcounts[], const MPI_Aint rdispls[],
const MPI_Datatype recvtypes[], MPI_Comm comm, MPI_Request *request)
int MPI_Neighbor_alltoallw_init(const void *sendbuf, const int sendcounts[],
const MPI_Aint sdispls[], const MPI_Datatype sendtypes[],
void *recvbuf, const int recvcounts[], const MPI_Aint rdispls[],
const MPI_Datatype recvtypes[], MPI_Comm comm, MPI_Info info, MPI_Request *request)
π Fortran Syntax
USE MPI
! or the older form: INCLUDE 'mpif.h'
MPI_NEIGHBOR_ALLTOALLW(SENDBUF, SENDCOUNTS, SDISPLS, SENDTYPES,
RECVBUF, RECVCOUNTS, RDISPLS, RECVTYPES, COMM, IERROR)
<type> SENDBUF(*), RECVBUF(*)
INTEGER SENDCOUNTS(*), SENDTYPES(*)
INTEGER RECVCOUNTS(*), RECVTYPES(*)
INTEGER(KIND=MPI_ADDRESS_KIND) SDISPLS(*), RDISPLS(*)
INTEGER COMM, IERROR
MPI_INEIGHBOR_ALLTOALLW(SENDBUF, SENDCOUNTS, SDISPLS, SENDTYPES,
RECVBUF, RECVCOUNTS, RDISPLS, RECVTYPES, COMM, REQUEST, IERROR)
<type> SENDBUF(*), RECVBUF(*)
INTEGER SENDCOUNTS(*), SENDTYPES(*)
INTEGER RECVCOUNTS(*), RECVTYPES(*)
INTEGER(KIND=MPI_ADDRESS_KIND) SDISPLS(*), RDISPLS(*)
INTEGER COMM, REQUEST, IERROR
MPI_NEIGHBOR_ALLTOALLW_INIT(SENDBUF, SENDCOUNTS, SDISPLS, SENDTYPES,
RECVBUF, RECVCOUNTS, RDISPLS, RECVTYPES, COMM, INFO, REQUEST, IERROR)
<type> SENDBUF(*), RECVBUF(*)
INTEGER SENDCOUNTS(*), SENDTYPES(*)
INTEGER RECVCOUNTS(*), RECVTYPES(*)
INTEGER(KIND=MPI_ADDRESS_KIND) SDISPLS(*), RDISPLS(*)
INTEGER COMM, INFO, REQUEST, IERROR
π Fortran 2008 Syntax
USE mpi_f08
MPI_Neighbor_alltoallw(sendbuf, sendcounts, sdispls, sendtypes, recvbuf,
recvcounts, rdispls, recvtypes, comm, ierror)
TYPE(*), DIMENSION(..), INTENT(IN) :: sendbuf
TYPE(*), DIMENSION(..) :: recvbuf
INTEGER, INTENT(IN) :: sendcounts(*), recvcounts(*)
INTEGER(KIND=MPI_ADDRESS_KIND), INTENT(IN) :: sdispls(*), rdispls(*)
TYPE(MPI_Datatype), INTENT(IN) :: sendtypes(*), recvtypes(*)
TYPE(MPI_Comm), INTENT(IN) :: comm
INTEGER, OPTIONAL, INTENT(OUT) :: ierror
MPI_Ineighbor_alltoallw(sendbuf, sendcounts, sdispls, sendtypes, recvbuf,
recvcounts, rdispls, recvtypes, comm, request, ierror)
TYPE(*), DIMENSION(..), INTENT(IN), ASYNCHRONOUS :: sendbuf
TYPE(*), DIMENSION(..), ASYNCHRONOUS :: recvbuf
INTEGER, INTENT(IN), ASYNCHRONOUS :: sendcounts(*), recvcounts(*)
INTEGER(KIND=MPI_ADDRESS_KIND), INTENT(IN), ASYNCHRONOUS ::
sdispls(*), rdispls(*)
TYPE(MPI_Datatype), INTENT(IN), ASYNCHRONOUS :: sendtypes(*),
recvtypes(*)
TYPE(MPI_Comm), INTENT(IN) :: comm
TYPE(MPI_Request), INTENT(OUT) :: request
INTEGER, OPTIONAL, INTENT(OUT) :: ierror
MPI_Neighbor_alltoallw_init(sendbuf, sendcounts, sdispls, sendtypes, recvbuf,
recvcounts, rdispls, recvtypes, comm, info, request, ierror)
TYPE(*), DIMENSION(..), INTENT(IN), ASYNCHRONOUS :: sendbuf
TYPE(*), DIMENSION(..), ASYNCHRONOUS :: recvbuf
INTEGER, INTENT(IN), ASYNCHRONOUS :: sendcounts(*), recvcounts(*)
INTEGER(KIND=MPI_ADDRESS_KIND), INTENT(IN), ASYNCHRONOUS ::
sdispls(*), rdispls(*)
TYPE(MPI_Datatype), INTENT(IN), ASYNCHRONOUS :: sendtypes(*),
recvtypes(*)
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β starting address of the send buffer. where the goods live, bestie π«Άsendcountsβ integer array where entry i says how many elements you're sending to neighbor i.sdisplsβ integer array where entry i says the displacement (in bytes, offset fromsendbuf) from which to send data to neighbor i.sendtypesβ datatype array where entry i says which datatype to use when sending data to neighbor i. this is the β¨spicyβ¨ part β every neighbor can get a different type.recvcountsβ integer array where entry j says how many elements you're receiving from neighbor j.rdisplsβ integer array where entry j says the displacement (in bytes, offset fromrecvbuf) where data from neighbor j should be written.recvtypesβ datatype array where entry j says which datatype to use when receiving data from neighbor j.commβ the communicator over which data is to be exchanged. the group chat itself πinfoβ Info (handle, persistent only).
π OUTPUT PARAMETERS π
recvbufβ address of the receive buffer.requestβ Request (handle, non-blocking only).ierrorβ Fortran only: error status.
π DESCRIPTION π
MPI_Neighbor_alltoallw is a generalized collective operation where all processes send data to and receive data from all their neighbors. it's MPI_Neighbor_alltoallv but with extra β¨le flexibilityβ¨: you get to specify the datatype of individual data blocks, on top of displacement and element count. like, not just "how much" but "what kind of thing" too. obsessed.
you can think of it like this: each process does 2n independent point-to-point communications, where n is the number of neighbors in the topology of communicator comm. and the neighbors + buffer layout? determined by the topology of comm. slay.
MPI_Cart_get(comm, maxdims, dims, periods, coords);
for (dim = 0, i = 0 ; dim < dims ; ++dim) {
MPI_Cart_shift(comm, dim, 1, &r0, &r1);
MPI_Isend(sendbuf + sdispls[i] * extent(sendtype),
sendcount, sendtypes[i], r0, ..., comm, ...);
MPI_Irecv(recvbuf + rdispls[i] * extent(recvtype),
recvcount, recvtypes[i], r0, ..., comm, ...);
++i;
MPI_Isend(sendbuf + sdispls[i] * extent(sendtype),
sendcount, sendtypes[i], r1, ..., comm, &req[i]);
MPI_Irecv(recvbuf + rdispls[i] * extent(recvtype),
recvcount, recvtypes[i], r1, ..., comm, ...);
++i;
}
MPI_Wait_all (...);
MPI_Comm_size(comm, &n);
for (i = 0, i < n; i++)
MPI_Send(sendbuf + sdispls[i], sendcounts[i],
sendtypes[i], i, ..., comm);
for (i = 0, i < n; i++)
MPI_Recv(recvbuf + rdispls[i], recvcounts[i],
recvtypes[i], i, ..., comm);
process j sends the k-th block of its local sendbuf to neighbor k, which places the data in the j-th block of its local recvbuf. it's giving perfectly choreographed π¦ coordination.
when a pair of processes exchanges data, each may pass different element count and datatype arguments β as long as the sender specifies the same amount of data to send (in bytes) as the receiver expects to receive. the byte counts have to match, periodt. π
note that process i may send a different amount of data to process j than it receives from process j. also, a process may send entirely different amounts and types of data to different processes in the communicator. it's asymmetric and it's iconic.
π₯ NOTES π₯
- the
MPI_IN_PLACEoption forsendbufis not meaningful for this operation. don't try it π - the specification of counts, types, and displacements should not cause any location to be written more than once. like, no double-writing, bestie, that's chaos π
- all arguments on all processes are significant. the
commargument, in particular, must describe the same communicator on all processes. everyone has to agree on the group chat or it's not the same group chat. - the offsets of
sdisplsandrdisplsare measured in bytes. compare this toMPI_Neighbor_alltoallv, where these offsets are measured in units ofsendtypeandrecvtype, respectively. yes, this is a trap. yes, we've all fallen in it. π
okay wait, that's only part 1 β there's more coming, don't go anywhere πβ¨
β¨ ERRORS β¨
Okay bestie, story time: basically every single MPI routine hands you back an error value. In C it's the return value of the function, and in Fortran it's that pesky last argument. No escaping it, that's just the vibe. π
But before that error value ever reaches you, something else happens first β the current MPI error handler attached to the communication object (think communicator, window, file, whatever) gets called. And if there's no communication object tied to the MPI call at all? Then the call gets treated as attached to MPI_COMM_SELF and it calls the handler associated with that instead. π«Ά
Now, when MPI_COMM_SELF isn't initialized yet (like before MPI_Init / MPI_Init_thread, after MPI_Finalize, or if you're running the Sessions Model exclusively), the error raises the initial error handler instead. You can swap that initial error handler out by:
- calling
MPI_Comm_set_errhandleronMPI_COMM_SELFwhen you're using the World model, or - using the
mpi_initial_errhandlerCLI argument withmpiexec, or the info key forMPI_Comm_spawn/MPI_Comm_spawn_multiple.
And if nothing else appropriate was set? Then MPI_ERRORS_RETURN gets called for MPI I/O functions, and MPI_ERRORS_ABORT gets called for literally every other MPI function. π That's just how it goes.
Three iconic predefined error handlers (Open MPI ships with these)
MPI_ERRORS_ARE_FATALβ causes the program to abort all connected MPI processes. Yep, everyone. Gone. πMPI_ERRORS_ABORTβ an error handler you can invoke on a communicator, window, file, or session. Called on a communicator, it acts as ifMPI_Abortwas called on that communicator. Called on a window or file, it acts as ifMPI_Abortwas called on a communicator containing the group of processes in the corresponding window or file. Called on a session, it aborts only the local process.MPI_ERRORS_RETURNβ returns an error code back to the application. Polite king. π
Wanna write your own error handler? Slay, you absolutely can π₯
MPI applications can implement their own by calling:
MPI_Comm_create_errhandlerthenMPI_Comm_set_errhandlerMPI_File_create_errhandlerthenMPI_File_set_errhandlerMPI_Session_create_errhandlerthenMPI_Session_set_errhandler(or atMPI_Session_init)MPI_Win_create_errhandlerthenMPI_Win_set_errhandler
β οΈ Heads up bestie: MPI does not guarantee that an MPI program can continue past an error. Like, no promises. Plan accordingly. π
Check the MPI man page for the full list of MPI error codes, and the Error Handling section of the MPI-3.1 standard if you want the deep lore.
π See also
MPI_Neighbor_alltoallMPI_Neighbor_alltoallvMPI_Cart_createMPI_Graph_createMPI_Dist_graph_create
π Copyright
2003-2026, The Open MPI Community
And that's the whole page, bestie β we're done fr fr! π¦ This was MPI_NEIGHBOR_ALLTOALLW_INIT(3), dated Sep 10, 2026, brought to you by the The Open MPI Community. Go forth and neighbor-alltoallw-init responsibly. Periodt. πβ¨πΈ
π¦ 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