The short answer is yes, datatypes must match, but there are some caveats.
When using primitive MPI datatypes such as MPI_INT
and MPI_FLOAT
, the types must be identical. The only exception is MPI_PACKED
, which can match any other type.
When using derived datatypes (a.k.a. user-defined datatypes), things get slightly more complicated. A general MPI datatype consists of two things: a type signature, which defines the basic language datatypes that make up the derived datatype, and a series of byte displacements, which define where those basic elements reside in memory. The combination of both sequences is called the type map of the datatype. The primitive MPI datatypes are particular cases of such general datatypes having a single basic datatype in the type signature with a displacement of 0, e.g. MPI_INT
has the following type map: { (int, 0) }
. For a Send and Receive operation to match, the type signature must be the same on both sides, but the displacements can vary. E.g. the sender might send a single MPI_Type_contiguous
object consisting of 3 MPI_FLOAT
s, but the receiver can receive this as an MPI_Type_indexed
type of 3 MPI_FLOAT
s with arbitrary displacements. The sender might also supply an array of 3 MPI_FLOAT
elements, e.g. MPI_Send(buf, 3, MPI_FLOAT, ...)
and this would still result in the same type signature.
I should emphasize that the type signature consists of basic datatypes only. Whether the user-defined datatype was created directly from primitive MPI types or other user-defined datatypes (or a mixture of thereof) is irrelevant.
Example: the sender defines an MPI_Type_struct
consisting of 3 MPI_INT
s and 2 MPI_FLOAT
s. The receiver defines an MPI_Type_contiguous
consisting of 3 MPI_INT
s (let's call this type A
), another MPI_Type_contiguous
of 2 MPI_FLOAT
s (type B
), and then an MPI_Type_struct
consisting of 1 A
and 1 B
. These two datatypes will match, since ultimately they're both 3 int
s followed by 2 float
s.