| 202 | | |
| | 202 | Here is how these primitives could be used to implement an MPI program: |
| | 203 | |
| | 204 | {{{ |
| | 205 | #define MPI_ANY_SOURCE $COMM_ANY_SOURCE |
| | 206 | #define MPI_ANY_TAG $COMM_ANY_TAG |
| | 207 | #define MPI_INT 1 |
| | 208 | #define MPI_FLOAT 2 |
| | 209 | #define MPI_DOUBLE 3 |
| | 210 | // etc. |
| | 211 | |
| | 212 | $input int NPROCS; |
| | 213 | $assume NPROCS >= 1; |
| | 214 | $scope top; |
| | 215 | $proc procs[NPROCS]; |
| | 216 | |
| | 217 | typedef $comm *MPI_Comm; |
| | 218 | $comm MPI_Comm_world_comm; |
| | 219 | MPI_Comm *MPI_COMM_WORLD = &_MPI_COMM_WORLD; |
| | 220 | boolean initialized = $false; |
| | 221 | |
| | 222 | /* This structure tells you the source and tag of a received message, |
| | 223 | * which you need if you used wildcards, Also size. |
| | 224 | */ |
| | 225 | typedef struct MPI_Status { |
| | 226 | int source; |
| | 227 | int tag; |
| | 228 | int size; |
| | 229 | } MPI_Status; |
| | 230 | |
| | 231 | typedef int MPI_Datatype; |
| | 232 | |
| | 233 | int sizeofDatatype(MPI_Datatype type) { |
| | 234 | switch (type) { |
| | 235 | case MPI_INT: return sizeof(int); |
| | 236 | case MPI_FLOAT: return sizeof(float); |
| | 237 | case MPI_DOUBLE: return sizeof(double); |
| | 238 | default: exit(-1); // not yet implemented |
| | 239 | } |
| | 240 | } |
| | 241 | |
| | 242 | void MPI_Comm_init(MPI_Comm comm) { |
| | 243 | $when (initialized) ; |
| | 244 | } |
| | 245 | |
| | 246 | void MPI_Send(int pid, void *buf, int count, MPI_Datatype type, int dest, int tag, MPI_Comm comm) { |
| | 247 | $message m = $message_pack(pid, dest, tag, buf, sizeofDatatype(type)*count); |
| | 248 | |
| | 249 | $comm_enqueue(comm, &m); |
| | 250 | } |
| | 251 | |
| | 252 | void MPI_Recv(int pid, void *buf, int count, MPI_Datataype type, int source, int tag, MPI_Comm comm, MPI_Status *status) { |
| | 253 | int size = sizeofDatatype(type)*count; |
| | 254 | // the following is a system function with built-in guard: |
| | 255 | $message m = $comm_dequeue(comm, source, pid, tag); |
| | 256 | |
| | 257 | status->size = $message_size(&m); |
| | 258 | status->source = $message_source(&m); |
| | 259 | status->dest = $message_dest(&m); |
| | 260 | $message_unpack(&m, buf, size); // will throw exception if message too big |
| | 261 | } |
| | 262 | |
| | 263 | void MPI_process(int pid) { |
| | 264 | ... |
| | 265 | MPI_Comm_init(MPI_COMM_WORLD); |
| | 266 | ... |
| | 267 | } |
| | 268 | |
| | 269 | void main() { |
| | 270 | for (int i=0; i<NPROCS; i++) procs[i] = $spawn MPI_process(i); |
| | 271 | MPI_Comm_world_comm = $comm_create(NPROCS, &procs[0]); |
| | 272 | initialized = $true; |
| | 273 | for (int i=0; i<NPROCS; i++) $wait procs[i]; |
| | 274 | } |
| | 275 | }}} |
| | 276 | |
| | 277 | |