# Since this module is a thin wrapper around OpenMPI, in case of missing
# documentation, you can refer to https://www.open-mpi.org/doc/v1.8/.
module mpi is
- c_compiler_option(exec("mpicc", "-showme:compile"))
- c_linker_option(exec("mpicc", "-showme:link"))
+ cflags exec("mpicc", "-showme:compile")
+ ldflags exec("mpicc", "-showme:link")
end
import c
intrude import standard::string
import serialization
-private import json_serialization
+private import json::serialization
in "C Header" `{
#include <mpi.h>
fun send(data: nullable Serializable, dest: Rank, tag: Tag, comm: Comm)
do
# Serialize data
- var stream = new StringOStream
+ var stream = new StringWriter
var serializer = new JsonSerializer(stream)
serializer.serialize(data)
# Deserialize message
var deserializer = new JsonDeserializer(buffer)
var deserialized = deserializer.deserialize
-
+
if deserialized == null then print "|{buffer}|{buffer.chars.join("-")}| {buffer.length}"
return deserialized
end
+ # Send an empty buffer, only for the `tag`
fun send_empty(dest: Rank, tag: Tag, comm: Comm): SuccessOrError
`{
return MPI_Send(NULL, 0, MPI_CHAR, dest, tag, comm);
`}
+ # Receive an empty buffer, only for the `tag`
fun recv_empty(dest: Rank, tag: Tag, comm: Comm): SuccessOrError
`{
return MPI_Recv(NULL, 0, MPI_CHAR, dest, tag, comm, MPI_STATUS_IGNORE);
`}
- fun native_send(data: NativeCArray, count: Int, data_type: DataType, dest: Rank, tag: Tag, comm: Comm): SuccessOrError
+ # Send a `NativeCArray` `buffer` with a given `count` of `data_type`
+ fun native_send(buffer: NativeCArray, count: Int, data_type: DataType, dest: Rank, tag: Tag, comm: Comm): SuccessOrError
`{
- return MPI_Send(data, count, data_type, dest, tag, comm);
+ return MPI_Send(buffer, count, data_type, dest, tag, comm);
`}
- fun native_recv(data: NativeCArray, count: Int, data_type: DataType, dest: Rank, tag: Tag, comm: Comm, status: Status): SuccessOrError
+ # Receive into a `NativeCArray` `buffer` with a given `count` of `data_type`
+ fun native_recv(buffer: NativeCArray, count: Int, data_type: DataType, dest: Rank, tag: Tag, comm: Comm, status: Status): SuccessOrError
`{
- return MPI_Recv(data, count, data_type, dest, tag, comm, status);
+ return MPI_Recv(buffer, count, data_type, dest, tag, comm, status);
`}
+ # Probe for the next data to receive, store the result in `status`
+ #
+ # Note: If you encounter an error where the next receive does not correspond
+ # to the last `probe`, call this method twice to ensure a correct result.
fun probe(source: Rank, tag: Tag, comm: Comm, status: Status): SuccessOrError
`{
return MPI_Probe(source, tag, comm, status);
# An MPI communicator
extern class Comm `{ MPI_Comm `}
+ # The _null_ communicator, targeting no processors
new null_ `{ return MPI_COMM_NULL; `}
+
+ # The _world_ communicator, targeting all processors
new world `{ return MPI_COMM_WORLD; `}
+
+ # The _self_ communicator, targeting this processor only
new self_ `{ return MPI_COMM_SELF; `}
# Number of processors in this communicator
fun size: Int `{
int size;
- MPI_Comm_size(recv, &size);
+ MPI_Comm_size(self, &size);
return size;
`}
# Rank on this processor in this communicator
fun rank: Rank `{
int rank;
- MPI_Comm_rank(recv, &rank);
+ MPI_Comm_rank(self, &rank);
return rank;
`}
end
# An MPI data type
extern class DataType `{ MPI_Datatype `}
+ # Get a MPI char.
new char `{ return MPI_CHAR; `}
+
+ # Get a MPI short.
new short `{ return MPI_SHORT; `}
+
+ # Get a MPI int.
new int `{ return MPI_INT; `}
+
+ # Get a MPI long.
new long `{ return MPI_LONG; `}
+
+ # Get a MPI long long.
new long_long `{ return MPI_LONG_LONG; `}
+
+ # Get a MPI unsigned char.
new unsigned_char `{ return MPI_UNSIGNED_CHAR; `}
+
+ # Get a MPI unsigned short.
new unsigned_short `{ return MPI_UNSIGNED_SHORT; `}
+
+ # Get a MPI unsigned int.
new unsigned `{ return MPI_UNSIGNED; `}
+
+ # Get a MPI unsigned long.
new unsigned_long `{ return MPI_UNSIGNED_LONG; `}
+
+ # Get a MPI unsigned long long.
new unsigned_long_long `{ return MPI_UNSIGNED_LONG_LONG; `}
+
+ # Get a MPI float.
new float `{ return MPI_FLOAT; `}
+
+ # Get a MPI double.
new double `{ return MPI_DOUBLE; `}
+
+ # Get a MPI long double.
new long_double `{ return MPI_LONG_DOUBLE; `}
+
+ # Get a MPI byte.
new byte `{ return MPI_BYTE; `}
end
new `{ return malloc(sizeof(MPI_Status)); `}
# Source of this communication
- fun source: Rank `{ return recv->MPI_SOURCE; `}
+ fun source: Rank `{ return self->MPI_SOURCE; `}
# Tag of this communication
- fun tag: Tag `{ return recv->MPI_TAG; `}
+ fun tag: Tag `{ return self->MPI_TAG; `}
# Success or error on this communication
- fun error: SuccessOrError `{ return recv->MPI_ERROR; `}
+ fun error: SuccessOrError `{ return self->MPI_ERROR; `}
# Count of the given `data_type` in this communication
fun count(data_type: DataType): Int
`{
int count;
- MPI_Get_count(recv, data_type, &count);
+ MPI_Get_count(self, data_type, &count);
return count;
`}
end
# An MPI operation
#
-# Used with the `reduce` method
+# Used with the `reduce` method.
+#
+# See <http://www.mpi-forum.org/docs/mpi-1.1/mpi-11-html/node78.html>
extern class Op `{ MPI_Op `}
+ # Get a MPI null operation.
new op_null `{ return MPI_OP_NULL; `}
+
+ # Get a MPI maximum operation.
new max `{ return MPI_MAX; `}
+
+ # Get a MPI minimum operation.
new min `{ return MPI_MIN; `}
+
+ # Get a MPI sum operation.
new sum `{ return MPI_SUM; `}
+
+ # Get a MPI product operation.
new prod `{ return MPI_PROD; `}
+
+ # Get a MPI logical and operation.
new land `{ return MPI_LAND; `}
+
+ # Get a MPI bit-wise and operation.
new band `{ return MPI_BAND; `}
+
+ # Get a MPI logical or operation.
new lor `{ return MPI_LOR; `}
+
+ # Get a MPI bit-wise or operation.
new bor `{ return MPI_BOR; `}
+
+ # Get a MPI logical xor operation.
new lxor `{ return MPI_LXOR; `}
+
+ # Get a MPI bit-wise xor operation.
new bxor `{ return MPI_BXOR; `}
+
+ # Get a MPI minloc operation.
+ #
+ # Used to compute a global minimum and also an index attached
+ # to the minimum value.
+ #
+ # See <http://www.mpi-forum.org/docs/mpi-1.1/mpi-11-html/node79.html#Node79>
new minloc `{ return MPI_MINLOC; `}
+
+ # Get a MPI maxloc operation.
+ #
+ # Used to compute a global maximum and also an index attached
+ # to the maximum value.
+ #
+ # See <http://www.mpi-forum.org/docs/mpi-1.1/mpi-11-html/node79.html#Node79>
new maxloc `{ return MPI_MAXLOC; `}
+
+ # Get a MPI replace operation.
new replace `{ return MPI_REPLACE; `}
end
# An MPI return code to report success or errors
extern class SuccessOrError `{ int `}
# Is this a success?
- fun is_success: Bool `{ return recv == MPI_SUCCESS; `}
+ fun is_success: Bool `{ return self == MPI_SUCCESS; `}
# Is this an error?
fun is_error: Bool do return not is_success
fun error_class: ErrorClass
`{
int class;
- MPI_Error_class(recv, &class);
+ MPI_Error_class(self, &class);
return class;
`}
redef fun to_s do return native_to_s.to_s
private fun native_to_s: NativeString `{
char *err = malloc(MPI_MAX_ERROR_STRING);
- MPI_Error_string(recv, err, NULL);
+ MPI_Error_string(self, err, NULL);
return err;
`}
end
redef fun to_s do return native_to_s.to_s
private fun native_to_s: NativeString `{
char *err = malloc(MPI_MAX_ERROR_STRING);
- MPI_Error_string(recv, err, NULL);
+ MPI_Error_string(self, err, NULL);
return err;
`}
end
# An MPI rank within a communcator
extern class Rank `{ int `}
+ # Special rank accepting any processor
new any `{ return MPI_ANY_SOURCE; `}
# This Rank as an `Int`
- fun to_i: Int `{ return recv; `}
+ fun to_i: Int `{ return self; `}
redef fun to_s do return to_i.to_s
end
# An MPI tag, can be defined using `Int::tag`
extern class Tag `{ int `}
+ # Special tag accepting any tag
new any `{ return MPI_ANY_TAG; `}
# This tag as an `Int`
- fun to_i: Int `{ return recv; `}
+ fun to_i: Int `{ return self; `}
redef fun to_s do return to_i.to_s
end
redef universal Int
# `self`th MPI rank
- fun rank: Rank `{ return recv; `}
+ fun rank: Rank `{ return self; `}
# Tag identified by `self`
- fun tag: Tag `{ return recv; `}
+ fun tag: Tag `{ return self; `}
# Is this value undefined according to MPI? (may be returned by `Status::count`)
- fun is_undefined: Bool `{ return recv == MPI_UNDEFINED; `}
+ fun is_undefined: Bool `{ return self == MPI_UNDEFINED; `}
end
# Something sendable directly and efficiently over MPI