MPI_PACK_EXTERNAL(3)

πŸ’… MPI_PACK_EXTERNAL(3) πŸ’…

okay bestie, welcome to the Open MPI manual, section 3, and yes we are about to make MPI_Pack_external make sense. it's giving "portable data format era" and honestly? obsessed. grab a strawberry, we're going in. πŸ“


🌸 NAME 🌸

MPI_Pack_external β€” writes data to a portable format. that's the whole assignment, and it ate. ✨


✨ SYNTAX ✨

C Syntax

#include <mpi.h>

int MPI_Pack_external(const char *datarep, const void *inbuf,
     int incount, MPI_Datatype datatype,
     void *outbuf, MPI_Aint outsize,
     MPI_Aint *position)

Fortran Syntax

USE MPI
! or the older form: INCLUDE 'mpif.h'
MPI_PACK_EXTERNAL(DATAREP, INBUF, INCOUNT, DATATYPE,
     OUTBUF, OUTSIZE, POSITION, IERROR)

     INTEGER         INCOUNT, DATATYPE, IERROR
     INTEGER(KIND=MPI_ADDRESS_KIND) OUTSIZE, POSITION
     CHARACTER*(*)   DATAREP
     <type>          INBUF(*), OUTBUF(*)

Fortran 2008 Syntax

USE mpi_f08
MPI_Pack_external(datarep, inbuf, incount, datatype, outbuf, outsize,
             position, ierror)
     CHARACTER(LEN=*), INTENT(IN) :: datarep
     TYPE(*), DIMENSION(..), INTENT(IN) :: inbuf
     TYPE(*), DIMENSION(..) :: outbuf
     INTEGER, INTENT(IN) :: incount
     TYPE(MPI_Datatype), INTENT(IN) :: datatype
     INTEGER(KIND=MPI_ADDRESS_KIND), INTENT(IN) :: outsize
     INTEGER(KIND=MPI_ADDRESS_KIND), INTENT(INOUT) :: position
     INTEGER, OPTIONAL, INTENT(OUT) :: ierror

πŸŽ€ INPUT PARAMETERS πŸŽ€

  • datarep β€” the data representation, as a string. this is the vibe of the format itself πŸ’œ
  • inbuf β€” where the input buffer starts (a choice).
  • incount β€” how many input data items we're dealing with (integer).
  • datatype β€” the datatype of each of those input items (handle).
  • outsize β€” the size of the output buffer, measured in bytes (integer).

πŸ”„ INPUT/OUTPUT PARAMETER πŸ”„

  • position β€” where you currently are in the buffer, in bytes (integer). it comes in with a value and leaves with a new value, main character behaviour honestly 🫢

πŸ’Œ OUTPUT PARAMETERS πŸ’Œ

  • outbuf β€” where the output buffer starts (choice).
  • ierror β€” Fortran only: the error status (integer).

🌈 DESCRIPTION 🌈

MPI_Pack_external packs your data into the external32 format β€” a universal data representation that the MPI Forum defined. this format is so useful when you're exchanging data between different MPI implementations, or when you're writing data out to a file. no cap. πŸ“

your input buffer is specified by inbuf, incount and datatype, and it can be any communication buffer that's allowed in MPI_Send. meanwhile outbuf, your output buffer, has to be a contiguous storage area holding outsize bytes. that part is not negotiable bestie.

the input value of position is the first position in outbuf that gets used for packing β€” and it's measured in bytes, not elements, relative to the start of the buffer. when the function returns, position has been incremented by the size of the packed message, so it now points to the first location in outbuf that follows the packed message. the way that means you can just hand it straight to a subsequent call to MPI_Pack_external? iconic. πŸ”₯

Example: here's an example using MPI_Pack_external:

int position, i;
double msg[5];
char buf[1000];

...

MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
if (myrank == 0) {      /* SENDER CODE */
        position = 0;
        i = 5; /* number of doubles in msg[] */
        MPI_Pack_external("external32", &i, 1, MPI_INT,
            buf, 1000, &position);
        MPI_Pack_external("external32", &msg, i, MPI_DOUBLE,
            buf, 1000, &position);
        MPI_Send(buf, position, MPI_BYTE, 1, 0,
            MPI_COMM_WORLD);
} else {                /* RECEIVER CODE */
        MPI_Recv(buf, 1, MPI_BYTE, 0, 0, MPI_COMM_WORLD,
            MPI_STATUS_IGNORE);
        MPI_Unpack_external("external32", buf, 1000,
            MPI_INT, &i, 1, &position);
        MPI_Unpack_external("external32", buf, 1000,
            MPI_DOUBLE, &msg, i, &position);
}

πŸ“ NOTES πŸ“

datarep is the argument that says what data format you want. the only valid value in the current version of MPI is "external32". the argument exists purely for future extensibility, so don't go inventing your own strings, bestie πŸ™ˆ

to actually understand how pack and unpack behave, the move is to think of the data part of a message as the sequence you get by concatenating the successive values sent in that message. the pack operation stores that sequence into the buffer space, like it's sending the message to that buffer. the unpack operation retrieves the sequence from buffer space, like it's receiving a message from that buffer. (and if you need a mental model: it's a lot like internal Fortran files, or sscanf in C.)

you can pack several messages successively into one packing unit. how? several successive related calls to MPI_Pack_external, where the very first call provides position=0, and every call after that takes the position value output by the previous call, along with the same values for outbuf and outcount. that packing unit now holds the equivalent information that would have been stored in a message by one send call whose send buffer is the "concatenation" of the individual send buffers. slay.

a packing unit can be sent using type MPI_BYTE. any point-to-point or collective communication function can move that sequence of bytes from one process to another. and then that packing unit can be received using any receive operation with any datatype. (btw the type-matching rules are relaxed for messages sent with type MPI_BYTE β€” free real estate.)

a packing unit can also be unpacked into several successive messages. that happens via several successive related calls to MPI_Unpack_external, where the first call provides position=0, and each successive call takes the position value output by the previous call, plus the same values for inbuf and insize.

⚠️ and here's the part you do not skip: the concatenation of two packing units is not necessarily a packing unit, and a substring of a packing unit is not necessarily a packing unit. so you cannot concatenate two packing units and then unpack the result as one packing unit, and you cannot unpack a substring of a packing unit as a separate packing unit. every packing unit that a related sequence of pack calls created has to be unpacked as a unit by a sequence of related unpack calls. periodt. πŸ’€

πŸ’₯ ERRORS πŸ’₯

almost all MPI routines return an error value β€” C routines hand it back as the return result of the function, and Fortran routines put it in the last argument.

before that error value comes back, the current MPI error handler associated with the communication object (think communicator, window, file) gets called. if there's no communication object associated with the MPI call, then the call counts as attached to MPI_COMM_SELF and it will call the associated MPI error handler. when MPI_COMM_SELF isn't initialized (meaning: 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. 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 via the mpi_initial_errhandler CLI argument to mpiexec, or via an info key to MPI_Comm_spawn/MPI_Comm_spawn_multiple. and if 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.

Open MPI ships three predefined error handlers you can use:

  • MPI_ERRORS_ARE_FATAL β€” causes the program to abort all connected MPI processes. yeah. all of them. 😭
  • MPI_ERRORS_ABORT β€” an error handler you can invoke 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. if it's called on a session, it aborts only the local process.
  • MPI_ERRORS_RETURN β€” returns an error code to the application. gentle. polite. 🌸

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

  • MPI_Comm_create_errhandler and then MPI_Comm_set_errhandler
  • MPI_File_create_errhandler and then MPI_File_set_errhandler
  • MPI_Session_create_errhandler and then MPI_Session_set_errhandler, or at MPI_Session_init
  • MPI_Win_create_errhandler and then MPI_Win_set_errhandler
πŸ’€ note that MPI does not guarantee that an MPI program can continue past an error. so like. don't bank on it.

check the MPI man page for a full list of MPI error codes. and check the Error Handling section of the MPI-3.1 standard if you want even more lore.

See also:

  • MPI_Pack_external_size
  • MPI_Send
  • MPI_Unpack_external
  • sscanf(3C)

2003-2026, The Open MPI Community


and that's the whole page bestie, you're officially fluent in MPI_Pack_external 🧚✨ this one came out of the Open MPI manual β€” the page is MPI_PACK_EXTERNAL(3) β€” and it's dated Sep 10, 2026. go forth and pack portably. πŸ’–πŸ¦‹πŸŒˆ

πŸ“¦ where this page comes from