MPI_NEIGHBOR_ALLTOALL_INIT(3)

πŸ“¦
version 5.0.10 Β· 4 versions
, in ubuntu stonking

πŸ’– MPI_NEIGHBOR_ALLTOALL_INIT πŸ’–

okay bestie, gather round, because this is the Open MPI manual page for MPI_NEIGHBOR_ALLTOALL_INIT(3) and honestly? it's giving "everybody talks to everybody, but make it topology". πŸ¦‹


✨ NAME ✨

MPI_Neighbor_alltoall, MPI_Ineighbor_alltoall, MPI_Neighbor_alltoall β€” all processes send data to neighboring processes in a virtual topology communicator</p> πŸ’…

(yes bestie, MPI_Neighbor_alltoall really does show up twice in that list. that's not me being messy, that's literally what the page says. steady. 🫢)


🌸 SYNTAX 🌸

πŸ’œ 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 send buffer (choice). it's where your outgoing lil data go πŸ’Œ
  • sendcount β€” number of elements to send to each process (integer).
  • sendtype β€” datatype of send buffer elements (handle).
  • recvcount β€” number of elements to receive from each process (integer).
  • recvtype β€” datatype of receive buffer elements (handle).
  • comm β€” communicator over which data is to be exchanged (handle). the group chat, basically πŸ’¬
  • info β€” Info (handle, persistent only). this one only shows up for the persistent girlies.

πŸŽ€ OUTPUT PARAMETERS πŸŽ€

  • recvbuf β€” starting address of receive buffer (choice). incoming mail slot πŸ“¬
  • request β€” Request (handle, non-blocking only).
  • ierror β€” Fortran only: error status (integer).

πŸ’– DESCRIPTION πŸ’–

okay so MPI_Neighbor_alltoall is a collective operation where every process sends and receives the same amount of data to each neighbor. the way this routine actually works, bestie, is that each process performs 2n independent point-to-point communications (where n is the number of neighbors in communicator comm). the neighbors and the buffer layout? all determined by the topology of comm. 🌈

Example of MPI_Neighbor_alltoall semantics for cartesian topologies:

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 each process breaks its local sendbuf up into n blocks β€” every one of them 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 neighbor k drops that data into the j-th block of its local recvbuf. πŸ”₯

the amount of data sent must be equal to the amount of data received, pairwise, between every pair of processes. no cap, that's the rule. πŸ’€

πŸ¦‹ NEIGHBOR ORDERING πŸ¦‹

okay this part is lowkey the most important bit so pay attention bestie πŸ‘‘

  • for a distributed graph topology, created with MPI_Dist_graph_create, the sequence of neighbors in the send and receive buffers at each process is defined as the sequence returned by MPI_Dist_graph_neighbors for destinations and sources, respectively.
  • for a general graph topology, created with MPI_Graph_create, the order of neighbors in the send and receive buffers is defined as the sequence of neighbors as returned by MPI_Graph_neighbors.
  • > heads up: general graph topologies should generally be replaced by the distributed graph topologies. it's giving ✨ upgrade era ✨
  • for a Cartesian topology, created 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 and then in the positive direction with displacement 1. 🧭
  • the numbers of sources and destinations in the communication routines are 2*ndims, with ndims defined in MPI_Cart_create.
  • if a neighbor does not exist β€” like, at the border of a Cartesian topology in the case of a non-periodic virtual grid dimension (i.e., periods[…]==false) β€” then this neighbor is defined to be MPI_PROC_NULL.

and if a neighbor in any of the functions is MPI_PROC_NULL, then the neighborhood collective communication behaves like a point-to-point communication with MPI_PROC_NULL in this direction. that is: the buffer is still part of the sequence of neighbors, but it is neither communicated nor updated. it's there, it's just not doing anything. main character energy, honestly. πŸ’…


🌈 NOTES 🌈

  • the MPI_IN_PLACE option for sendbuf is not meaningful for this function.
  • all arguments on all processes are significant. the comm argument, in particular, must describe the same communicator on all processes. and comm must 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_alltoallv lets 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_alltoallw expands MPI_Neighbor_alltoallv's functionality to allow the exchange of data with different datatypes. πŸ‘‘

⭐ still with me? good. more coming. ⭐

πŸ’€ ERRORS πŸ’€

okay bestie, error time, don't freak out πŸ’…

Almost all MPI routines hand back an error value β€” and yeah, that means basically all of them. In C it's the return result of the function, and in Fortran it shows up in the last argument. that's just how she is πŸŽ€

Before that error value ever gets returned to you, the current MPI error handler associated with the communication object gets called β€” think communicator, window, file, the whole squad. ✨

If there's no communication object associated with the MPI call, then that call is considered attached to MPI_COMM_SELF and it will call the associated MPI error handler. self-attached, main character energy, we love to see it πŸ‘‘

And when MPI_COMM_SELF is not initialized β€” i.e., before MPI_Init / MPI_Init_thread, after MPI_Finalize, or when you're using the Sessions Model exclusively β€” the error raises the initial error handler. 😭

Good news tho: the initial error handler can be changed! 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 the info key to MPI_Comm_spawn / MPI_Comm_spawn_multiple. custom error handling? slay πŸ’…

And if no other appropriate error handler has been set, then the MPI_ERRORS_RETURN error handler is called for MPI I/O functions, while the MPI_ERRORS_ABORT error handler is called for all other MPI functions. no cap ⭐

Open MPI includes three predefined error handlers that you can use, and they are iconic:

  • MPI_ERRORS_ARE_FATAL β€” causes the program to abort all connected MPI processes. yeah. everyone. all of them. πŸ’€
  • 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 if MPI_Abort was called on that communicator. If it's 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. And if it's called on a session, it aborts only the local process. nuanced 🫢
  • MPI_ERRORS_RETURN β€” returns an error code to the application. simple. clean. hands it right back ✨

MPI applications can also implement their own error handlers by calling:

  • 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
⚠️ note that MPI does not guarantee that an MPI program can continue past an error. like… it might not. don't bank on it bestie 😭

See the MPI man page for a full list of MPI error codes. And see the Error Handling section of the MPI-3.1 standard for more information. iykyk πŸ“š

See also:

  • MPI_Neighbor_alltoallv
  • MPI_Neighbor_alltoallw
  • MPI_Cart_create
  • MPI_Graph_create
  • MPI_Dist_graph_create
  • MPI_Dist_graph_create_adjacent

2003-2026, The Open MPI Community


and that's the whole page, bestie!! πŸ¦‹πŸ’– this one came from the Open MPI community, dated Sep 10, 2026, and it lives in the manual as MPI_NEIGHBOR_ALLTOALL_INIT(3). go forth and neighbor-alltoall-init responsibly, you're gonna do amazing πŸ₯°πŸŒΈβœ¨

πŸ“¦ where this page comes from