MPI_INEIGHBOR_ALLTOALL(3)
π MPI_INEIGHBOR_ALLTOALL π
okay bestie so this is a page from the Open MPI manual, and it's all about MPI_Neighbor_alltoall, MPI_Ineighbor_alltoall, and MPI_Neighbor_alltoall_init β the trio of neighbor-exchange collectives. yes the manpage name is MPI_INEIGHBOR_ALLTOALL(3) (iykyk, the non-blocking one got top billing) but the whole squad lives here. let's get into it β¨
π SYNOPSIS π
β¨ C Syntax β¨
#include <mpi.h>
int MPI_Neighbor_alltoall(const void *sendbuf, int sendcount,
MPI_Datatype sendtype, void *recvbuf, int recvcount,
MPI_Datatype recvtype, MPI_Comm comm)
int MPI_Ineighbor_alltoall(const void *sendbuf, int sendcount,
MPI_Datatype sendtype, void *recvbuf, int recvcount,
MPI_Datatype recvtype, MPI_Comm comm, MPI_Request *request)
int MPI_Neighbor_alltoall_init(const void *sendbuf, int sendcount,
MPI_Datatype sendtype, void *recvbuf, int recvcount,
MPI_Datatype recvtype, MPI_Comm comm, MPI_Info info, MPI_Request *request)
π Fortran Syntax π
USE MPI
! or the older form: INCLUDE 'mpif.h'
MPI_NEIGHBOR_ALLTOALL(SENDBUF, SENDCOUNT, SENDTYPE, RECVBUF, RECVCOUNT,
RECVTYPE, COMM, IERROR)
<type> SENDBUF(*), RECVBUF(*)
INTEGER SENDCOUNT, SENDTYPE, RECVCOUNT, RECVTYPE
INTEGER COMM, IERROR
MPI_INEIGHBOR_ALLTOALL(SENDBUF, SENDCOUNT, SENDTYPE, RECVBUF, RECVCOUNT,
RECVTYPE, COMM, REQUEST, IERROR)
<type> SENDBUF(*), RECVBUF(*)
INTEGER SENDCOUNT, SENDTYPE, RECVCOUNT, RECVTYPE
INTEGER COMM, REQUEST, IERROR
MPI_NEIGHBOR_ALLTOALL_INIT(SENDBUF, SENDCOUNT, SENDTYPE, RECVBUF, RECVCOUNT,
RECVTYPE, COMM, INFO, REQUEST, IERROR)
<type> SENDBUF(*), RECVBUF(*)
INTEGER SENDCOUNT, SENDTYPE, RECVCOUNT, RECVTYPE
INTEGER COMM, INFO, REQUEST, IERROR
π¦ Fortran 2008 Syntax π¦
USE mpi_f08
MPI_Neighbor_alltoall(sendbuf, sendcount, sendtype, recvbuf, recvcount,
recvtype, comm, ierror)
TYPE(*), DIMENSION(..), INTENT(IN) :: sendbuf
TYPE(*), DIMENSION(..) :: recvbuf
INTEGER, INTENT(IN) :: sendcount, recvcount
TYPE(MPI_Datatype), INTENT(IN) :: sendtype, recvtype
TYPE(MPI_Comm), INTENT(IN) :: comm
INTEGER, OPTIONAL, INTENT(OUT) :: ierror
MPI_Ineighbor_alltoall(sendbuf, sendcount, sendtype, recvbuf, recvcount,
recvtype, comm, request, ierror)
TYPE(*), DIMENSION(..), INTENT(IN), ASYNCHRONOUS :: sendbuf
TYPE(*), DIMENSION(..), ASYNCHRONOUS :: recvbuf
INTEGER, INTENT(IN) :: sendcount, recvcount
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_Neighbor_alltoall_init(sendbuf, sendcount, sendtype, recvbuf, recvcount,
recvtype, comm, info, request, ierror)
TYPE(*), DIMENSION(..), INTENT(IN), ASYNCHRONOUS :: sendbuf
TYPE(*), DIMENSION(..), ASYNCHRONOUS :: recvbuf
INTEGER, INTENT(IN) :: sendcount, recvcount
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β starting address of the send buffer (choice, bestie, you pick the type).sendcountβ how many elements you're sending to each process (integer).sendtypeβ datatype of the send buffer elements (handle).recvcountβ how many elements you're receiving from each process (integer).recvtypeβ datatype of the receive buffer elements (handle).commβ the communicator the data gets exchanged over (handle).infoβ info (handle, persistent only).
π«Ά OUTPUT PARAMETERS π«Ά
recvbufβ starting address of the receive buffer (choice).requestβ request (handle, non-blocking only).ierrorβ Fortran only: error status (integer).
π DESCRIPTION π
so MPI_Neighbor_alltoall is a collective operation where every process sends and receives the same amount of data to each of its neighbors. the way this actually pops off: each process runs 2n independent point-to-point communications, where n is the number of neighbors in communicator comm. the neighbors themselves and the buffer layout? determined by the topology of comm. no cap.
here's what MPI_Neighbor_alltoall semantics look like for cartesian topologies, bestie:
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 + i * sendcount * extent(sendtype),
sendcount, sendtype, r0, ..., comm, ...);
MPI_Irecv(recvbuf + i * recvcount * extent(recvtype),
recvcount, recvtype, r0, ..., comm, ...);
++i;
MPI_Isend(sendbuf + i * sendcount * extent(sendtype),
sendcount, sendtype, r1, ..., comm, &req[i]);
MPI_Irecv(recvbuf + i * recvcount * extent(recvtype),
recvcount, recvtype, r1, ..., comm, ...);
++i;
}
MPI_Waitall (...);
so the vibe is: each process breaks its local sendbuf into n blocks β each one holding sendcount elements of type sendtype β and splits its recvbuf the same way according to recvcount and recvtype. process j sends the k-th block of its local sendbuf to neighbor k, and that neighbor drops the data into the j-th block of its local recvbuf. π
β οΈ the amount of data sent must equal the amount of data received, pairwise, between every pair of processes. it's giving symmetry or it's giving nothing.
π NEIGHBOR ORDERING π
okay this part is lowkey important, so pay attention bestie:
- distributed graph topology (made with
MPI_Dist_graph_create): the sequence of neighbors in the send and receive buffers at each process is defined as the sequence returned byMPI_Dist_graph_neighborsβ for destinations and sources, respectively. β¨ - general graph topology (made with
MPI_Graph_create): the order of neighbors in the send and receive buffers is the sequence of neighbors as returned byMPI_Graph_neighbors. heads up though β general graph topologies should generally be replaced by the distributed graph topologies. it's giving "old faithful, but the new one ate". - Cartesian topology (made with
MPI_Cart_create): the sequence of neighbors in the send and receive buffers at each process is defined by order of the dimensions β first the neighbor in the negative direction, then in the positive direction, with displacement1. the numbers of sources and destinations in the communication routines are2*ndims, withndimsdefined inMPI_Cart_create. and if a neighbor doesn't exist (i.e., you're at the border of a Cartesian topology in the case of a non-periodic virtual grid dimension, i.e.,periods[β¦]==false), then that neighbor is defined to beMPI_PROC_NULL.
and if a neighbor in any of these functions is MPI_PROC_NULL, the neighborhood collective communication behaves like a point-to-point communication with MPI_PROC_NULL in that direction. translation: the buffer is still part of the sequence of neighbors, but it is neither communicated nor updated. it's there, it's just not participating. π
π₯ NOTES π₯
- the
MPI_IN_PLACEoption forsendbufis not meaningful for this function. don't do it, it's not that girl. - all arguments on all processes are significant.
commin particular must describe the same communicator on all processes, andcommmust be either a cartesian, graph, or dist graph communicator. - there are two MPI library functions that are more general than
MPI_Neighbor_alltoall:MPI_Neighbor_alltoallvlets you do all-to-all communication to and from buffers that need not be contiguous β different processes may send and receive different amounts of data. πMPI_Neighbor_alltoallwexpandsMPI_Neighbor_alltoallv's functionality to allow the exchange of data with different datatypes. iconic.
π ERRORS π
okay bestie, listen up, because this is the part that saves you at 3am π«Ά
- basically almost every MPI routine hands you back an error value: C routines give it to you as the return value of the function, and Fortran routines put it in the last argument. that's the vibe. β¨
- before that error value ever comes back to you, the current MPI error handler that's tied to the communication object (think: communicator, window, file) gets called. if there's no communication object attached to the MPI call, then the call is treated as attached to
MPI_COMM_SELFand it'll call the associated MPI error handler instead. π - and when
MPI_COMM_SELFisn't initialized yet (that's beforeMPI_Init/MPI_Init_thread, or afterMPI_Finalize, or if you're living that Sessions Model exclusively life), the error raises the initial error handler. you can swap that initial error handler out by callingMPI_Comm_set_errhandleronMPI_COMM_SELFwhen you're on the World model, or with thempi_initial_errhandlerCLI argument tompiexec, or the info key toMPI_Comm_spawn/MPI_Comm_spawn_multiple. π - if no other appropriate error handler has been set, then
MPI_ERRORS_RETURNgets called for MPI I/O functions, andMPI_ERRORS_ABORTgets called for all other MPI functions. that's just the default, no cap.
π the three predefined error handlers Open MPI ships with π
MPI_ERRORS_ARE_FATALβ Causes the program to abort all connected MPI processes. it's giving nuclear option, and honestly? sometimes that's the move πMPI_ERRORS_ABORTβ An error handler that can be invoked on a communicator, window, file, or session. When it's called on a communicator, it acts as ifMPI_Abortwas called on that communicator. If it's 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. If it's called on a session, it aborts only the local process. very demure, very mindful of scope πMPI_ERRORS_RETURNβ Returns an error code to the application. it just hands you the receipt and lets you deal. π
π¦ and you can make your own, because of course you can π¦
MPI applications can also implement their own error handlers by calling:
MPI_Comm_create_errhandlerthenMPI_Comm_set_errhandlerMPI_File_create_errhandlerthenMPI_File_set_errhandlerMPI_Session_create_errhandlerthenMPI_Session_set_errhandleror atMPI_Session_initMPI_Win_create_errhandlerthenMPI_Win_set_errhandler
β οΈ heads up bestie: note that MPI does not guarantee that an MPI program can continue past an error. like, it might, it might not, that's not something you get to assume. plan accordingly. π
see the MPI man page for a full list of MPI error codes. π
see the Error Handling section of the MPI-3.1 standard for more information. (iykyk, go read the standard, it's right there π)
π«Ά See also π«Ά
MPI_Neighbor_alltoallvMPI_Neighbor_alltoallwMPI_Cart_createMPI_Graph_createMPI_Dist_graph_createMPI_Dist_graph_create_adjacent
πΈ Copyright πΈ
2003-2026, The Open MPI Community
and that's a wrap, bestie π this page came to you from the Open MPI crew, dated Sep 10, 2026, and yes it's MPI_INEIGHBOR_ALLTOALL(3) β go forth and neighbor-alltoall responsibly. slay. β¨ππ¦
π¦ 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