MPI_ALLTOALLW(3)
π MPI_ALLTOALLW π
okay bestie, so this is MPI_ALLTOALLW(3) from the Open MPI manual, and it's literally the glow-up edition of all-to-all π¦
MPI_Alltoallw, plus its chaotic little siblings MPI_Ialltoallw and MPI_Alltoallw_init β all processes send data of different types to, and receive data of different types from, all processes. every single one. no cap. π
β¨ SYNTAX β¨
πΈ C Syntax πΈ
#include <mpi.h>
int MPI_Alltoallw(const void *sendbuf, const int sendcounts[],
const int sdispls[], const MPI_Datatype sendtypes[],
void *recvbuf, const int recvcounts[], const int rdispls[],
const MPI_Datatype recvtypes[], MPI_Comm comm)
int MPI_Ialltoallw(const void *sendbuf, const int sendcounts[],
const int sdispls[], const MPI_Datatype sendtypes[],
void *recvbuf, const int recvcounts[], const int rdispls[],
const MPI_Datatype recvtypes[], MPI_Comm comm,
MPI_Request *request)
int MPI_Alltoallw_init(const void *sendbuf, const int sendcounts[],
const int sdispls[], const MPI_Datatype sendtypes[],
void *recvbuf, const int recvcounts[], const int 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_ALLTOALLW(SENDBUF, SENDCOUNTS, SDISPLS, SENDTYPES,
RECVBUF, RECVCOUNTS, RDISPLS, RECVTYPES, COMM, IERROR)
<type> SENDBUF(*), RECVBUF(*)
INTEGER SENDCOUNTS(*), SDISPLS(*), SENDTYPES(*)
INTEGER RECVCOUNTS(*), RDISPLS(*), RECVTYPES(*)
INTEGER COMM, IERROR
MPI_IALLTOALLW(SENDBUF, SENDCOUNTS, SDISPLS, SENDTYPES,
RECVBUF, RECVCOUNTS, RDISPLS, RECVTYPES, COMM, REQUEST, IERROR)
<type> SENDBUF(*), RECVBUF(*)
INTEGER SENDCOUNTS(*), SDISPLS(*), SENDTYPES(*)
INTEGER RECVCOUNTS(*), RDISPLS(*), RECVTYPES(*)
INTEGER COMM, REQUEST, IERROR
MPI_ALLTOALLW_INIT(SENDBUF, SENDCOUNTS, SDISPLS, SENDTYPES,
RECVBUF, RECVCOUNTS, RDISPLS, RECVTYPES, COMM, INFO, REQUEST, IERROR)
<type> SENDBUF(*), RECVBUF(*)
INTEGER SENDCOUNTS(*), SDISPLS(*), SENDTYPES(*)
INTEGER RECVCOUNTS(*), RDISPLS(*), RECVTYPES(*)
INTEGER COMM, INFO, REQUEST, IERROR
π¦ Fortran 2008 Syntax π¦
USE mpi_f08
MPI_Alltoallw(sendbuf, sendcounts, sdispls, sendtypes, recvbuf, recvcounts,
rdispls, recvtypes, comm, ierror)
TYPE(*), DIMENSION(..), INTENT(IN) :: sendbuf
TYPE(*), DIMENSION(..) :: recvbuf
INTEGER, INTENT(IN) :: sendcounts(*), sdispls(*), recvcounts(*),
rdispls(*)
TYPE(MPI_Datatype), INTENT(IN) :: sendtypes(*)
TYPE(MPI_Datatype), INTENT(IN) :: recvtypes(*)
TYPE(MPI_Comm), INTENT(IN) :: comm
INTEGER, OPTIONAL, INTENT(OUT) :: ierror
MPI_Ialltoallw(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(*), sdispls(*),
recvcounts(*), 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_Alltoallw_init(sendbuf, sendcounts, sdispls, sendtypes, recvbuf,
recvcounts, rdispls, recvtypes, comm, fIinfo, request, ierror)
TYPE(*), DIMENSION(..), INTENT(IN), ASYNCHRONOUS :: sendbuf
TYPE(*), DIMENSION(..), ASYNCHRONOUS :: recvbuf
INTEGER, INTENT(IN), ASYNCHRONOUS :: sendcounts(*), sdispls(*),
recvcounts(*), 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
(yes bestie, that fIinfo is really in there, i'm not gonna touch it, it's canon π
)
π INPUT PARAMETERS π
sendbufβ starting address of the send buffer. the origin point, the home base πsendcountsβ integer array, where entryispecifies the number of elements to send to ranki. one number per bestie β¨sdisplsβ integer array, where entryispecifies the displacement (in bytes, offset fromsendbuf) from which to send data to ranki. bytes, bestie, not elements. remember that π«Άsendtypesβ datatype array, where entryispecifies the datatype to use when sending data to ranki. every rank gets to be special πrecvcountsβ integer array, where entryjspecifies the number of elements to receive from rankjrdisplsβ integer array, where entryjspecifies the displacement (in bytes, offset fromrecvbuf) to which data from rankjshould be writtenrecvtypesβ datatype array, where entryjspecifies the datatype to use when receiving data from rankj. equal opportunity type chaos πcommβ communicator over which data is to be exchangedinfoβ Info (handle, persistent only)
π OUTPUT PARAMETERS π
recvbufβ address of receive bufferrequestβ Request (handle, non-blocking only)ierrorβ Fortran only: error status
π DESCRIPTION π
MPI_Alltoallw is a generalized collective operation where all processes send data to and receive data from all other processes. it's giving main character energy, but for every process simultaneously π
it adds flexibility to MPI_Alltoallv by letting you specify the datatype of individual data blocks β on top of displacement and element count. so not just "how much" and "where", but also "as what". obsessed π
you can think of its operation like this, where each process performs 2n independent point-to-point communications (with n being the number of processes in communicator comm), including communication with itself:
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 process k, which places the data in the j-th block of its local recvbuf. so cute. so symmetric. π
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. bytes are the vibe check here πΈ
note that processimay send a different amount of data to processjthan it receives from processj. also, a process may send entirely different amounts and types of data to different processes in the communicator. it's giving "no two relationships are the same" π¦
π WHEN COMMUNICATOR IS AN INTER-COMMUNICATOR π
when the communicator is an inter-communicator, the gather operation occurs in two phases. the data is gathered from all the members of the first group and received by all the members of the second group. then the data is gathered from all the members of the second group and received by all the members of the first. the operation exhibits a symmetric, full-duplex behavior. iconic, honestly β¨
the first group defines the root process. the root process uses MPI_ROOT as the value of root. all other processes in the first group use MPI_PROC_NULL as the value of root. all processes in the second group use the rank of the root process in the first group as the value of root.
when the communicator is an intra-communicator, these groups are the same, and the operation occurs in a single phase. one phase, one slay π
π USE OF IN-PLACE OPTION π
when the communicator is an intracommunicator, you can perform an all-to-all operation in-place β meaning the output buffer is used as the input buffer. just use the variable MPI_IN_PLACE as the value of sendbuf. β¨
in that case, sendcounts, sdispls, and sendtypes are ignored. the input data of each process is assumed to be in the area where that process would receive its own contribution to the receive buffer. it's already home, bestie π π«Ά
π NOTES π
- the specification of counts, types, and displacements should not cause any location to be written more than once. seriously. that's undefined behavior territory and we don't go there π
- all arguments on all processes are significant. the
commargument, in particular, must describe the same communicator on all processes. everybody on the same page, fr fr - the offsets of
sdisplsandrdisplsare measured in bytes. compare this toMPI_Alltoallv, where these offsets are measured in units ofsendtypeandrecvtype, respectively. iykyk β this is the trap, don't fall in it π
π₯ ERRORS π₯
okay so bestie, here's the tea on errors, and it's kinda important so like, pay attention πΈ
Almost all MPI routines return an error value. In C routines that's the return result of the function, and in Fortran routines it's the last argument. iykyk π
Before that error value ever comes back to you, the current MPI error handler associated with the communication object (think communicator, window, file β the whole squad) gets called. And if there's no communication object tied to the MPI call? Then the call is considered attached to MPI_COMM_SELF and it'll call the associated MPI error handler. periodt.
Now here's the plot twist π β when MPI_COMM_SELF is not initialized (so: 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 instead.
You can change that initial error handler by calling MPI_Comm_set_errhandler on MPI_COMM_SELF when you're using the World model, or with the mpi_initial_errhandler CLI argument to mpiexec, or the info key to MPI_Comm_spawn/MPI_Comm_spawn_multiple. slay π
And if literally no other appropriate error handler has been set? Then MPI_ERRORS_RETURN gets called for MPI I/O functions, and MPI_ERRORS_ABORT gets called for all other MPI functions. that's just how it is bestie π
β¨ the three predefined error handlers β¨
Open MPI ships with three of these bad boys that you can use:
MPI_ERRORS_ARE_FATALβ Causes the program to abort all connected MPI processes. like, everyone goes down together π«Ά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 ifMPI_Abortwas called on that communicator. If 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 called on a session, it aborts only the local process.MPI_ERRORS_RETURNβ Returns an error code to the application. the chill one fr fr π
π make your own!! main character energy π
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
β οΈ Note that MPI does not guarantee that an MPI program can continue past an error. no cap, that one's real. don't be out here assuming you can just keep vibing after an error π
See the MPI man page for a full list of MPI error codes β that's your reference doc bestie, bookmark it π
See the Error Handling section of the MPI-3.1 standard for more information.
π¦ See also: π¦
MPI_AlltoallMPI_Alltoallv
π Copyright π
2003-2026, The Open MPI Community
and that's a wrap on MPI_ALLTOALLW(3) bestie!! πβ¨ this lil masterpiece is from the Open MPI source, version Sep 10, 2026 β go forth and alltoallw responsibly, mwah π
π«Ά
π¦ 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