Low-level API

The MPI.API submodule provides a low-level interface which closely matches the MPI C API. While these functions are not intended for general usage, they are useful for calling MPI routines not yet available in MPI.jl main interface, and is the basis for the high-level wrappers.

Large counts

The methods suffixed with _c are the MPI 4.0 large-count entry points: they take MPI_Count typed arguments where the others take int. The size of MPI_Count depends on the implementation, but usually allows 64-bit integer counts, so these are the methods to use for messages of more than typemax(Cint) elements.

They can be called against any supported MPI library. Where the library does not provide them, each MPI_Foo_c falls back to the narrow MPI_Foo at precompilation time. That is all-or-nothing: an implementation may ship only part of the set – Intel MPI 2021.11 has MPI_Send_c but not MPI_Type_size_c – and because the count types below are one choice for the whole package, using the large-count entry points that happen to be present would leave a Ref{MPI_Count} reaching an entry point that wants a Ptr{Cint}. A count that does not fit in an int then raises an InexactError instead of being silently truncated. MPI.API.HAS_LARGE_COUNT says which of the two is in use.

Note that having them does not by itself make messages of more than typemax(Cint) elements possible. Displacements and datatype extents are MPI_Aint, which is pointer-sized, so on a 32-bit build neither can describe more than 2 GiB however wide MPI_Count is – a 32-bit address space could not hold such a buffer anyway.

The fallback is transparent for a count passed by value, since ccall converts it, but not for one passed through a pointer. Type arrays and Refs with MPI.API.Count, MPI.API.Displ, or MPI.API.TypeDispl need to have the type corresponding to the entry point they use. For example, a Ref{MPI_Count} reaching a fallback that expects a Ptr{Cint} is a MethodError. (In other words, the fallback mechanism is always safe.)

Two functions taking callback arguments are deliberately excluded from that fallback because their callback signatures differ between their non-large-count and large-count versions: MPI_Op_create_c takes an MPI_User_function_c (whose len argument is an MPI_Count *) rather than an MPI_User_function (an int *), and MPI_Register_datarep_c likewise. Both raise MPI.FeatureLevelError on a library that does not provide them. It is fine to create an operator with a non-large-count version of these functions, and then call the large-count version of a reduction operation. (All MPI implementations we tested can automatically chunk large reduction counts when the registered operator cannot handle them in one go.)

Feature levels

Wrappers for procedures that the MPI library does not provide are replaced, when MPI.jl is precompiled, by a throw(MPI.FeatureLevelError). The reported minimum MPI version comes from a table derived from the MPI standard's machine-readable binding description; see MPI.jl/gen/versions/README.md. (Procedures that have been in MPI since 3.1 or earlier do not have such version information since MPI.jl requires MPI 3.0 or later anyway.)

MPI.API.@mpichkMacro
@mpichk ccall(...) [min_version] [fallback=MPI_Foo]

Wrap a ccall to an MPI procedure: call it via @mpicall and turn a nonzero return code into an MPIError.

If the symbol is absent from the MPI library, the whole body is replaced at macro-expansion time — that is, when MPI.jl is precompiled — by one of

  • a call to fallback with the same arguments, if given. This is how the large-count MPI_Foo_c wrappers fall back to the narrow MPI_Foo entry points on a pre-MPI-4.0 library: the two take the same arguments in the same order, and a count which is too large for the narrow interface then fails in ccall's conversion to Cint.

    Note the limit of that transparency: This only works for counts passed by value, which are converted by ccall. Counts passed through a pointer are not converted. Callers must therefore type arrays and Refs with Count, Displ or TypeDispl, which depend on the entry point they use. A Ref{MPI_Count} reaching a fallback that wants a Ptr{Cint} is a MethodError.

  • otherwise, throw(FeatureLevelError(name, min_version)).

min_version comes from the generator's INTRODUCED table.

source
MPI.API.HAS_LARGE_COUNTConstant
MPI.API.HAS_LARGE_COUNT

Whether the MPI library provides the MPI 4.0 large-count (MPI_*_c) entry points, as determined when MPI.jl is precompiled.

It is true only if the library provides every one of them, listed in MPI.API.LARGE_COUNT_SYMBOLS. An implementation may ship only some – Intel MPI 2021.11 has MPI_Send_c but not MPI_Type_size_c – and since MPI.API.Count and its companions are a single choice for the whole package, the entry points have to be used all together or not at all.

The MPI_*_c wrappers can be called either way: where this is false they fall back to the corresponding narrow entry point, and a count that does not fit in a Cint then raises an InexactError.

source
MPI.API.CountType
MPI.API.Count

The integer type the high-level interface uses for element counts: MPI_Count if the library provides the MPI 4.0 large-count entry points, and Cint otherwise. See MPI.API.HAS_LARGE_COUNT.

source
MPI.API.DisplType
MPI.API.Displ

The integer type the high-level interface uses for the displacements of the "v" collectives (MPI.VBuffer): MPI_Aint if the library provides the MPI 4.0 large-count entry points, and Cint otherwise.

This is deliberately separate from MPI.API.Count: MPI_Alltoallv_c and friends widen their counts to MPI_Count, but widen their displacements only to MPI_Aint, and the two are not the same type on every ABI. (For example, in 32-bit MPICH, MPI_Count is Int64 while MPI_Aint is Int32.) Note that the derived-datatype constructors go the other way: MPI_Type_create_struct_c widens its byte displacements to MPI_Count.

source
MPI.API.TypeDisplType
MPI.API.TypeDispl

The integer type which the high-level interface uses for the byte displacements of the derived-datatype constructors (MPI.Types.create_struct and friends): MPI_Count if the library provides the MPI 4.0 large-count entry points, and MPI_Aint otherwise.

A third type is needed because the datatype constructors widen byte displacements from MPI_Aint all the way to MPI_Count, where the "v" collectives widen element displacements only from int to MPI_Aint, so neither MPI.API.Count nor MPI.API.Displ fits both. The three coincide on 64-bit ABIs.

source
MPI.API.MPI_AccumulateMethod
MPI_Accumulate(origin_addr, origin_count, origin_datatype, target_rank, target_disp, target_count, target_datatype, op, win)
source
MPI.API.MPI_Accumulate_cMethod
MPI_Accumulate_c(origin_addr, origin_count, origin_datatype, target_rank, target_disp, target_count, target_datatype, op, win)
  • MPI_Accumulate_c man page: MPICH
source
MPI.API.MPI_Alltoallv_cMethod
MPI_Alltoallv_c(sendbuf, sendcounts, sdispls, sendtype, recvbuf, recvcounts, rdispls, recvtype, comm)
  • MPI_Alltoallv_c man page: MPICH
source
MPI.API.MPI_Alltoallv_init_cMethod
MPI_Alltoallv_init_c(sendbuf, sendcounts, sdispls, sendtype, recvbuf, recvcounts, rdispls, recvtype, comm, info, request)
  • MPI_Alltoallv_init_c man page: MPICH
source
MPI.API.MPI_Alltoallw_cMethod
MPI_Alltoallw_c(sendbuf, sendcounts, sdispls, sendtypes, recvbuf, recvcounts, rdispls, recvtypes, comm)
  • MPI_Alltoallw_c man page: MPICH
source
MPI.API.MPI_Alltoallw_init_cMethod
MPI_Alltoallw_init_c(sendbuf, sendcounts, sdispls, sendtypes, recvbuf, recvcounts, rdispls, recvtypes, comm, info, request)
  • MPI_Alltoallw_init_c man page: MPICH
source
MPI.API.MPI_Gatherv_cMethod
MPI_Gatherv_c(sendbuf, sendcount, sendtype, recvbuf, recvcounts, displs, recvtype, root, comm)
  • MPI_Gatherv_c man page: MPICH
source
MPI.API.MPI_Gatherv_init_cMethod
MPI_Gatherv_init_c(sendbuf, sendcount, sendtype, recvbuf, recvcounts, displs, recvtype, root, comm, info, request)
  • MPI_Gatherv_init_c man page: MPICH
source
MPI.API.MPI_GetMethod
MPI_Get(origin_addr, origin_count, origin_datatype, target_rank, target_disp, target_count, target_datatype, win)
source
MPI.API.MPI_Get_accumulateMethod
MPI_Get_accumulate(origin_addr, origin_count, origin_datatype, result_addr, result_count, result_datatype, target_rank, target_disp, target_count, target_datatype, op, win)
source
MPI.API.MPI_Get_accumulate_cMethod
MPI_Get_accumulate_c(origin_addr, origin_count, origin_datatype, result_addr, result_count, result_datatype, target_rank, target_disp, target_count, target_datatype, op, win)
  • MPI_Get_accumulate_c man page: MPICH
source
MPI.API.MPI_Get_cMethod
MPI_Get_c(origin_addr, origin_count, origin_datatype, target_rank, target_disp, target_count, target_datatype, win)
  • MPI_Get_c man page: MPICH
source
MPI.API.MPI_Ialltoallv_cMethod
MPI_Ialltoallv_c(sendbuf, sendcounts, sdispls, sendtype, recvbuf, recvcounts, rdispls, recvtype, comm, request)
  • MPI_Ialltoallv_c man page: MPICH
source
MPI.API.MPI_Ialltoallw_cMethod
MPI_Ialltoallw_c(sendbuf, sendcounts, sdispls, sendtypes, recvbuf, recvcounts, rdispls, recvtypes, comm, request)
  • MPI_Ialltoallw_c man page: MPICH
source
MPI.API.MPI_Igather_cMethod
MPI_Igather_c(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm, request)
  • MPI_Igather_c man page: MPICH
source
MPI.API.MPI_Igatherv_cMethod
MPI_Igatherv_c(sendbuf, sendcount, sendtype, recvbuf, recvcounts, displs, recvtype, root, comm, request)
  • MPI_Igatherv_c man page: MPICH
source
MPI.API.MPI_Iscatterv_cMethod
MPI_Iscatterv_c(sendbuf, sendcounts, displs, sendtype, recvbuf, recvcount, recvtype, root, comm, request)
  • MPI_Iscatterv_c man page: MPICH
source
MPI.API.MPI_IsendrecvMethod
MPI_Isendrecv(sendbuf, sendcount, sendtype, dest, sendtag, recvbuf, recvcount, recvtype, source, recvtag, comm, request)
source
MPI.API.MPI_Isendrecv_cMethod
MPI_Isendrecv_c(sendbuf, sendcount, sendtype, dest, sendtag, recvbuf, recvcount, recvtype, source, recvtag, comm, request)
  • MPI_Isendrecv_c man page: MPICH
source
MPI.API.MPI_PcontrolMethod
MPI_Pcontrol(level::Integer)

Written by hand rather than generated: MPI_Pcontrol is the MPI C API's only variadic procedure, and Clang.jl does not generate wrappers for those. The standard leaves the arguments after level implementation-defined, and they are not exposed here.

The call has to be variadic even though it passes no variadic argument, which is why this uses @ccall's ; form rather than the @mpichk path everything else takes. Calling a variadic callee through a plain signature crashes: on x86-64 System V the callee reads al for the number of vector registers used, which a non-variadic call never sets, so va_start spills against garbage – Intel MPI segfaults. On 32-bit Windows it is worse still, because a variadic function is cdecl even where the rest of MS-MPI is stdcall, so @mpicall's stdcall fixup corrupts the stack.

On Unix the symbol is named without a library so that an LD_PRELOAD profiler can intercept it, matching what @mpicall does – this being exactly the procedure a profiling layer wants to see.

source
MPI.API.MPI_PutMethod
MPI_Put(origin_addr, origin_count, origin_datatype, target_rank, target_disp, target_count, target_datatype, win)
source
MPI.API.MPI_Put_cMethod
MPI_Put_c(origin_addr, origin_count, origin_datatype, target_rank, target_disp, target_count, target_datatype, win)
  • MPI_Put_c man page: MPICH
source
MPI.API.MPI_RaccumulateMethod
MPI_Raccumulate(origin_addr, origin_count, origin_datatype, target_rank, target_disp, target_count, target_datatype, op, win, request)
source
MPI.API.MPI_Raccumulate_cMethod
MPI_Raccumulate_c(origin_addr, origin_count, origin_datatype, target_rank, target_disp, target_count, target_datatype, op, win, request)
  • MPI_Raccumulate_c man page: MPICH
source
MPI.API.MPI_RgetMethod
MPI_Rget(origin_addr, origin_count, origin_datatype, target_rank, target_disp, target_count, target_datatype, win, request)
source
MPI.API.MPI_Rget_accumulateMethod
MPI_Rget_accumulate(origin_addr, origin_count, origin_datatype, result_addr, result_count, result_datatype, target_rank, target_disp, target_count, target_datatype, op, win, request)
source
MPI.API.MPI_Rget_accumulate_cMethod
MPI_Rget_accumulate_c(origin_addr, origin_count, origin_datatype, result_addr, result_count, result_datatype, target_rank, target_disp, target_count, target_datatype, op, win, request)
  • MPI_Rget_accumulate_c man page: MPICH
source
MPI.API.MPI_Rget_cMethod
MPI_Rget_c(origin_addr, origin_count, origin_datatype, target_rank, target_disp, target_count, target_datatype, win, request)
  • MPI_Rget_c man page: MPICH
source
MPI.API.MPI_RputMethod
MPI_Rput(origin_addr, origin_count, origin_datatype, target_rank, target_disp, target_count, target_datatype, win, request)
source
MPI.API.MPI_Rput_cMethod
MPI_Rput_c(origin_addr, origin_count, origin_datatype, target_rank, target_disp, target_count, target_datatype, win, request)
  • MPI_Rput_c man page: MPICH
source
MPI.API.MPI_Scatterv_init_cMethod
MPI_Scatterv_init_c(sendbuf, sendcounts, displs, sendtype, recvbuf, recvcount, recvtype, root, comm, info, request)
  • MPI_Scatterv_init_c man page: MPICH
source
MPI.API.MPI_SendrecvMethod
MPI_Sendrecv(sendbuf, sendcount, sendtype, dest, sendtag, recvbuf, recvcount, recvtype, source, recvtag, comm, status)
source
MPI.API.MPI_Sendrecv_cMethod
MPI_Sendrecv_c(sendbuf, sendcount, sendtype, dest, sendtag, recvbuf, recvcount, recvtype, source, recvtag, comm, status)
  • MPI_Sendrecv_c man page: MPICH
source
MPI.API.MPI_Type_create_darray_cMethod
MPI_Type_create_darray_c(size, rank, ndims, array_of_gsizes, array_of_distribs, array_of_dargs, array_of_psizes, order, oldtype, newtype)
  • MPI_Type_create_darray_c man page: MPICH
source
MPI.API.MPI_Type_get_contents_cMethod
MPI_Type_get_contents_c(datatype, max_integers, max_addresses, max_large_counts, max_datatypes, array_of_integers, array_of_addresses, array_of_large_counts, array_of_datatypes)
  • MPI_Type_get_contents_c man page: MPICH
source