File wavm/mpi.cpp

Defines

MPI_FUNC(str)
MPI_FUNC_ARGS(formatStr, ...)
namespace wasm

SYSCALL NUMBERING

Have a look in the sysroot at include/bits/syscall.h to determine the system call numbering.

Functions

bool isInPlace(U8 wasmPtr)
WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Init", I32, MPI_Init, I32 a, I32 b)

Sets up the MPI world. Arguments are argc/argv which are NULL, NULL in our case

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Get_version", I32, MPI_Get_version, I32 version, I32 subversion)

Returns the version of the standard corresponding to the current implementation.

TODO not implemented.

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Comm_size", I32, MPI_Comm_size, I32 comm, I32 resPtr)

Returns the number of ranks in the given communicator

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Comm_rank", I32, MPI_Comm_rank, I32 comm, I32 resPtr)

Returns the rank of the caller

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Comm_dup", I32, MPI_Comm_dup, I32 comm, I32 newComm)

Duplicates an existing communicator with all its cached information.

TODO not implemented.

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Comm_free", I32, MPI_Comm_free, I32 comm)

Mark a communicator object for deallocation

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Comm_split", I32, MPI_Comm_split, I32 comm, I32 color, I32 key, I32 newComm)

Creates new communicators based on colors and keys.

TODO not implemented.

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Comm_c2f", I32, MPI_Comm_c2f, I32 comm)

Returns a valid Fortran communicator handler

https://www.open-mpi.org/doc/v4.0/man3/MPI_Comm_c2f.3.php TODO not implemented

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Comm_f2c", I32, MPI_Comm_f2c, I32 fComm)

Returns a valid C communicator handler

https://www.open-mpi.org/doc/v4.0/man3/MPI_Comm_c2f.3.php TODO not implemented

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Send", I32, MPI_Send, I32 buffer, I32 count, I32 datatype, I32 destRank, I32 tag, I32 comm)

Sends a single point-to-point message

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Rsend", I32, MPI_Rsend, I32 buffer, I32 count, I32 datatype, I32 destRank, I32 tag, I32 comm)

Ready send: the user guarantees that a receive is already posted. TODO not implemented

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Isend", I32, MPI_Isend, I32 buffer, I32 count, I32 datatype, I32 destRank, I32 tag, I32 comm, I32 requestPtrPtr)

Sends a single async point-to-point message

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Get_count", I32, MPI_Get_count, I32 statusPtr, I32 datatype, I32 countPtr)

Returns the number of elements the given MPI_Status corresponds to.

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Recv", I32, MPI_Recv, I32 buffer, I32 count, I32 datatype, I32 sourceRank, I32 tag, I32 comm, I32 statusPtr)

Receives a single point-to-point message.

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Sendrecv", I32, MPI_Sendrecv, I32 sendBuf, I32 sendCount, I32 sendType, I32 destination, I32 sendTag, I32 recvBuf, I32 recvCount, I32 recvType, I32 source, I32 recvTag, I32 comm, I32 statusPtr)

Sends and receives a message.

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Irecv", I32, MPI_Irecv, I32 buffer, I32 count, I32 datatype, I32 sourceRank, I32 tag, I32 comm, I32 requestPtrPtr)

Receives a single asynchronous point-to-point message.

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Wait", I32, MPI_Wait, I32 requestPtrPtr, I32 status)

Waits for the asynchronous request to complete

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Waitall", I32, MPI_Waitall, I32 count, I32 requestArray, I32 statusArray)

Waits for all given communications to complete TODO not implemented

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Waitany", I32, MPI_Waitany, I32 count, I32 requestArray, I32 idx, I32 status)

Waits for any specified send or receive to complete TODO not implemented

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Abort", I32, MPI_Abort, I32 a, I32 b)
WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Finalize", I32, MPI_Finalize)
WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Probe", I32, MPI_Probe, I32 source, I32 tag, I32 comm, I32 statusPtr)

Populates the given status with info about an incoming message.

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Bcast", I32, MPI_Bcast, I32 buffer, I32 count, I32 datatype, I32 root, I32 comm)

Broadcasts a message. This is called by both senders and receivers of broadcasts.

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Barrier", I32, MPI_Barrier, I32 comm)

Barrier between all ranks in the given communicator. Called by every rank in the communicator.

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Scatter", I32, MPI_Scatter, I32 sendBuf, I32 sendCount, I32 sendType, I32 recvBuf, I32 recvCount, I32 recvType, I32 root, I32 comm)

Distributes an array of data between all ranks in the communicator

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Gather", I32, MPI_Gather, I32 sendBuf, I32 sendCount, I32 sendType, I32 recvBuf, I32 recvCount, I32 recvType, I32 root, I32 comm)

Pulls data from all ranks in a communicator into a single buffer.

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Allgather", I32, MPI_Allgather, I32 sendBuf, I32 sendCount, I32 sendType, I32 recvBuf, I32 recvCount, I32 recvType, I32 comm)

Each rank gathers data from all other ranks. Results in all seeing the same buffer.

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Allgatherv", I32, MPI_Allgatherv, I32 sendBuf, I32 sendCount, I32 sendType, I32 recvBuf, I32 recvCount, I32 dspls, I32 recvType, I32 comm)

Gathers data from all processes and delivers it to all. Each process may contribute a different amount of data.

TODO not implemented.

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Reduce", I32, MPI_Reduce, I32 sendBuf, I32 recvBuf, I32 count, I32 datatype, I32 op, I32 root, I32 comm)

Reduces data sent by all ranks in the communicator using the given operator.

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Reduce_scatter", I32, MPI_Reduce_scatter, I32 sendBuf, I32 recvBuf, I32 recvCount, I32 datatype, I32 op, I32 comm)

Combines values and scatters the results.

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Allreduce", I32, MPI_Allreduce, I32 sendBuf, I32 recvBuf, I32 count, I32 datatype, I32 op, I32 comm)

Reduces data from all ranks in the communicator into all ranks, i.e. an all-to-all reduce where each ends up with the same data.

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Scan", I32, MPI_Scan, I32 sendBuf, I32 recvBuf, I32 count, I32 datatype, I32 op, I32 comm)

Computes an inclusive scan (partial reduction). The operation returns, when run on process with rank i, the reduction of the values of processes 0, …, i (inclusive).

Reference implementation: https://github.com/open-mpi/ompi/blob/master/ompi/mpi/c/scan.c

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Alltoall", I32, MPI_Alltoall, I32 sendBuf, I32 sendCount, I32 sendType, I32 recvBuf, I32 recvCount, I32 recvType, I32 comm)

Sends an all-to-all message.

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Alltoallv", I32, MPI_Alltoallv, I32 sendBuf, I32 sendCount, I32 sdispls, I32 sendType, I32 recvBuf, I32 recvCount, I32 rdispls, I32 recvType, I32 comm)

All processes send different amount of data to, and receive different amount of data from, all processes.

TODO not implemented

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Get_processor_name", I32, MPI_Get_processor_name, I32 buf, I32 bufLen)

Returns the name of this host

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Type_size", I32, MPI_Type_size, I32 typePtr, I32 res)

Returns the size of the type.

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Alloc_mem", I32, MPI_Alloc_mem, I32 memSize, I32 info, I32 resPtrPtr)

Allocates memory on this host (equivalent to a malloc)

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Cart_create", I32, MPI_Cart_create, I32 commOld, I32 ndims, I32 dims, I32 periods, I32 reorder, I32 newCommPtrPtr)

Makes a new communicator to which Cartesian topology information has been attached. Note: In MPI, memory is allocated from within the function call, that’s why we allocate it here.

Reference implementation: https://github.com/open-mpi/ompi/blob/master/ompi/mca/topo/base/topo_base_cart_create.c

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Cart_rank", I32, MPI_Cart_rank, I32 comm, I32 coords, I32 rankPtr)

Determines process rank in communicator given Cartesian location.

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Cart_get", I32, MPI_Cart_get, I32 comm, I32 maxdims, I32 dims, I32 periods, I32 coords)

Retrieves the Cartesian topology information associated with a communicator.

MPI Topologies are pointless in a serverless environment. Therefore we return default values (2dim grid) basing on the current world size.

In particular we define a 2-dim grid with as many processors, leaving the rest as MPI_UNDEFINED.

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Cart_shift", I32, MPI_Cart_shift, I32 comm, I32 direction, I32 disp, I32 sourceRank, I32 destRank)

Returns the shifted source and destination ranks, given a shift direction and amount.

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Op_create", I32, MPI_Op_create, I32 userFn, I32 commute, I32 op)

Creates a user-defined combination function handle.

TODO not implemented.

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Op_free", I32, MPI_Op_free, I32 op)

Frees a user-defined combination function handle.

TODO not implemented.

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Win_create", I32, MPI_Win_create, I32 basePtr, I32 size, I32 dispUnit, I32 info, I32 comm, I32 winPtrPtr)

Creates a shared memory region (i.e. a chunk of Faasm state)

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Win_fence", I32, MPI_Win_fence, I32 assert, I32 winPtr)

Special type of barrier invoked to ensure all RMA operations have completed.

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Get", I32, MPI_Get, I32 recvBuf, I32 recvCount, I32 recvType, I32 sendRank, I32 sendOffset, I32 sendCount, I32 sendType, I32 winPtr)

One-sided get RDMA.

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Put", I32, MPI_Put, I32 sendBuf, I32 sendCount, I32 sendType, I32 recvRank, I32 recvOffset, I32 recvCount, I32 recvType, I32 winPtr)

One-sided write to shared memory.

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Win_free", I32, MPI_Win_free, I32 winPtr)

Cleans up the given window

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Win_get_attr", I32, MPI_Win_get_attr, I32 winPtr, I32 attrKey, I32 attrResPtrPtr, I32 flagResPtr)

Returns the value for a given attribute of a window.

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Free_mem", I32, MPI_Free_mem, I32 basePtr)
WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Request_free", I32, MPI_Request_free, I32 requestPtr)

Frees a communication request object. TODO not implemented

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Type_contiguous", I32, MPI_Type_contiguous, I32 count, I32 oldDatatypePtr, I32 newDatatypePtrPtr)
WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Type_free", I32, MPI_Type_free, I32 datatype)

Frees a data type

TODO not implemented.

WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Type_commit", I32, MPI_Type_commit, I32 datatypePtrPtr)
WAVM_DEFINE_INTRINSIC_FUNCTION (env, "MPI_Wtime", F64, MPI_Wtime)
void mpiLink()

Variables

static thread_local faabric::mpi::MpiContext executingContext
static thread_local std::unique_ptr<ContextWrapper> ctx = nullptr
class ContextWrapper

Convenience wrapper around the MPI context for use in the syscalls in this file.

Public Functions

inline explicit ContextWrapper()
inline void checkMpiComm(I32 wasmPtr)
inline faabric_datatype_t *getFaasmDataType(I32 wasmPtr)
inline void writeFaasmRequestId(I32 requestPtrPtr, I32 requestId)

We use a trick here to avoid allocating extra memory. Rather than create an actual struct for the MPI_Request, we just use the pointer to hold the value of its ID

inline I32 getFaasmRequestId(I32 requestPtrPtr)

This uses the same trick, where we read the value of the pointer as the request ID.

inline faabric_info_t *getFaasmInfoType(I32 wasmPtr)
inline faabric_op_t *getFaasmOp(I32 wasmOp)
template<typename T>
inline void writeMpiResult(I32 resPtr, T result)

Public Members

WAVMWasmModule *module
Runtime::Memory *memory
MpiWorld &world
int rank