source: CIVL/include/impls/mpi.cvl@ 1aaefd4

main test-branch
Last change on this file since 1aaefd4 was ea777aa, checked in by Alex Wilton <awilton@…>, 3 years ago

Moved examples, include, build_default.properties, common.xml, and README out from dev.civl.com into the root of the repo.

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@5704 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 25.1 KB
RevLine 
[bf584ca]1#ifndef __CIVL_MPI__
[d109d6b]2#define __CIVL_MPI__
[4d9f19e]3
[a374423]4#include <seq.cvh>
[4209e90]5#include <civlc.cvh>
[d109d6b]6#include <concurrency.cvh>
7#include <bundle.cvh>
8#include <mpi.h>
[3af26ac]9#include <civl-mpi.cvh>
[566a657]10#include <stdlib.h>
11#include <string.h>
[e8f4e6a]12#include <pointer.cvh>
[ef8e46c]13#include <collate.cvh>
[1fbac22]14
[fecbb5a]15
16extern const int MPI_IN_PLACE_SPOT = 0;
17
[1fbac22]18/* Completed definition for mpi-common.h */
[d094548]19
[17ad6bf]20$mpi_state _mpi_state=_MPI_UNINIT;
21
[e15d0a3]22/************************** MPI LIB Implementations *******************************/
[17ad6bf]23
24int $mpi_init(void) {
25 $assert(_mpi_state == _MPI_UNINIT, "Process can only call MPI_Init() at most once.");
26 _mpi_state = _MPI_INIT;
27 return 0;
28}
29
30int MPI_Finalize(void) {
31 $assert(_mpi_state == _MPI_INIT, "Process can only call MPI_Finalize() after the "
32 "MPI enviroment is created and before cleaned.");
33 _mpi_state = _MPI_FINALIZED;
34 return 0;
35}
36
[2e6fe6f]37double MPI_Wtime() {
[1d71f60]38 double result;
[4209e90]39 int CMPI_time_count = $next_time_count();
[1d71f60]40
[17ad6bf]41 $assert(_mpi_state == _MPI_INIT, "MPI_Wtime() cannot be invoked "
[3ff27cf]42 "without MPI_Init() being called before.\n");
[ff51d87]43 result = $mpi_time(CMPI_time_count);
[4209e90]44 if (CMPI_time_count > 0) {
[566a657]45 $assume(result > $mpi_time(CMPI_time_count-1));
[4209e90]46 } else {
[3ff27cf]47 $assume(result > 0);
[4209e90]48 }
[2e6fe6f]49 return result;
50}
51
[e15d0a3]52int MPI_Comm_size(MPI_Comm comm, int *size) {
[537f004]53#ifndef _MPI_CONTRACT
[17ad6bf]54 $assert(_mpi_state == _MPI_INIT, "MPI_Comm_size() cannot be "
[3ff27cf]55 "invoked without MPI_Init() being called before.\n");
[537f004]56#endif
[566a657]57 *size = $mpi_comm_size(comm);
[e15d0a3]58 return 0;
59}
60
61int MPI_Comm_rank(MPI_Comm comm, int *rank) {
[537f004]62#ifndef _MPI_CONTRACT
[17ad6bf]63 $assert(_mpi_state == _MPI_INIT, "MPI_Comm_rank() cannot be "
[3ff27cf]64 "invoked without MPI_Init() being called before.\n");
[537f004]65#endif
[566a657]66 *rank = $mpi_comm_place(comm);
[e15d0a3]67 return 0;
68}
69
[112dfe0]70int MPI_Send(const void *buf, int count, MPI_Datatype datatype, int dest,
[e15d0a3]71 int tag, MPI_Comm comm) {
[938cccb]72 $assert(_mpi_state == _MPI_INIT, "MPI_Send() cannot be invoked "
73 "without MPI_Init() being called before.\n");
[5a071cc]74
[566a657]75#ifdef _MPI_NON_BLOCKING
[5a071cc]76 MPI_Request request;
[566a657]77
[5a071cc]78 $mpi_isend(buf, count, datatype, dest, tag, comm, &request);
79 $mpi_wait(&request, MPI_STATUS_IGNORE);
[566a657]80#elif defined(_MPI_BLOCKING)
81 $mpi_send(buf, count, datatype, dest, tag, comm);
82#endif
[5a071cc]83 return 1;
[e15d0a3]84}
85
[d094548]86int MPI_Isend(void *buf, int count, MPI_Datatype datatype, int dest,
87 int tag, MPI_Comm comm, MPI_Request * request) {
[a374423]88 $assert(_mpi_state == _MPI_INIT, "MPI_Isend() cannot be invoked "
[566a657]89 "without MPI_Init() being called before.\n");
90#ifdef _MPI_NON_BLOCKING
[5a071cc]91 return $mpi_isend(buf, count, datatype, dest, tag, comm, request);
[566a657]92#elif defined(_MPI_BLOCKING)
93 $assert(0, "MPI_Isend is not supported in the MPI blocking implementation.");
94 return 0;
95#endif
[6e93400]96}
97
98int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source,
99 int tag, MPI_Comm comm, MPI_Status *status) {
100 $assert(_mpi_state == _MPI_INIT, "MPI_Recv() cannot be invoked "
101 "without MPI_Init() being called before.\n");
[566a657]102#ifdef _MPI_NON_BLOCKING
[6e93400]103 MPI_Request request;
[566a657]104
[5a071cc]105 $mpi_irecv(buf, count, datatype, source, tag, comm, &request);
106 $mpi_wait(&request, status);
[566a657]107#elif defined(_MPI_BLOCKING)
108 $mpi_recv(buf, count, datatype, source, tag, comm, status);
109#endif
[d094548]110 return 1;
111}
112
[6e93400]113int MPI_Irecv(void *buf, int count, MPI_Datatype datatype, int source,
114 int tag, MPI_Comm comm, MPI_Request * request) {
115 $assert(_mpi_state == _MPI_INIT, "MPI_Irecv() cannot be invoked "
116 "without MPI_Init() being called before.\n");
[566a657]117#ifdef _MPI_NON_BLOCKING
[5a071cc]118 return $mpi_irecv(buf, count, datatype, source, tag, comm, request);
[566a657]119#elif defined(_MPI_BLOCKING)
120 $assert(0, "MPI_Irecv is not supported in the MPI blocking implementation.");
121 return 0;
122#endif
[d094548]123}
124
[a374423]125int MPI_Wait(MPI_Request * request, MPI_Status * status) {
126 $assert(_mpi_state == _MPI_INIT, "MPI_Wait() cannot be invoked "
127 "without MPI_Init() being called before.\n");
[566a657]128#ifdef _MPI_NON_BLOCKING
[5a071cc]129 $mpi_wait(request, status);
[566a657]130 return 1;
131#elif defined(_MPI_BLOCKING)
132 $assert(0, "MPI_Wait is not supported in the MPI blocking implementation.");
133 return 0;
134#endif
[a374423]135}
136
[d094548]137int MPI_Waitall(int count, MPI_Request array_of_requests[], MPI_Status array_of_statuses[]) {
[a374423]138 $assert(_mpi_state == _MPI_INIT, "MPI_Waitall() cannot be invoked "
139 "without MPI_Init() being called before.\n");
[566a657]140#ifdef _MPI_NON_BLOCKING
[d094548]141 $for (int i : 0 .. count-1) {
142 MPI_Status * status = array_of_statuses == MPI_STATUSES_IGNORE ? MPI_STATUS_IGNORE : array_of_statuses + i;
143 MPI_Request * req = array_of_requests + i;
[566a657]144
145 $mpi_wait(req, status);
[d094548]146 }
147 return 1;
[566a657]148#elif defined(_MPI_BLOCKING)
149 $assert(0, "MPI_Waitall is not supported in the MPI blocking implementation.");
150 return 0;
151#endif
[d094548]152}
153
154int MPI_Test(MPI_Request *request, int *flag, MPI_Status *status) {
[a374423]155 $assert(_mpi_state == _MPI_INIT, "MPI_Test() cannot be invoked "
156 "without MPI_Init() being called before.\n");
[566a657]157#ifdef _MPI_NON_BLOCKING
[5a071cc]158 if (*request == MPI_REQUEST_NULL) {
[566a657]159 *flag = 1;
[d094548]160 return 1;
[566a657]161 }
[a374423]162 $choose {
163 $when ($true) {
[5a071cc]164 $mpi_wait(request, status);
[a374423]165 *flag = 1;
166 }
[566a657]167 $when ($true)
[a374423]168 *flag = 0;
169 }
[d094548]170 return 1;
[566a657]171#elif defined(_MPI_BLOCKING)
172 $assert(0, "MPI_Test is not supported in the MPI blocking implementation.");
173 return 0;
174#endif
[d094548]175}
176
177int MPI_Request_free(MPI_Request * request) {
178 // The standard does not say this function accepts MPI_REQUEST_NULL
[566a657]179#ifdef _MPI_NON_BLOCKING
[d094548]180 $free(*request);
181 *request = MPI_REQUEST_NULL;
182 return 1;
[566a657]183#elif defined(_MPI_BLOCKING)
184 $assert(0, "MPI_Request_free is not supported in the MPI blocking implementation.");
185 return 0;
186#endif
[d094548]187}
188
[e15d0a3]189int MPI_Get_count(MPI_Status *status, MPI_Datatype datatype, int *count) {
[17ad6bf]190#ifndef _MPI_CONTRACT
191 $assert(_mpi_state == _MPI_INIT, "MPI_Get_count() cannot be invoked "
[3ff27cf]192 "without MPI_Init() being called before.\n");
[17ad6bf]193#endif
[e15d0a3]194 *count = status->size/sizeofDatatype(datatype);
195 return 0;
196}
197
[3d54c23]198int MPI_Get_processor_name(char * name, int * resultlen) {
199 $abstract int MPI_GET_PROCESSOR_NAME(char *, int *);
200
201 return MPI_GET_PROCESSOR_NAME(name, resultlen);
202}
203
[e15d0a3]204int MPI_Sendrecv(void *sendbuf, int sendcount, MPI_Datatype sendtype,
205 int dest, int sendtag,
206 void *recvbuf, int recvcount, MPI_Datatype recvtype,
207 int source, int recvtag,
208 MPI_Comm comm, MPI_Status *status) {
[938cccb]209 $assert(_mpi_state == _MPI_INIT, "MPI_Sendrecv() cannot be invoked "
210 "without MPI_Init() being called before.\n");
[9074a6e]211#ifdef _MPI_CONTRACT
212 $elaborate(dest);
213 $elaborate(source);
[17ad6bf]214#else
[c23f74e]215 $mpi_check_buffer(sendbuf, sendcount, sendtype);
[938cccb]216#endif
[42561ab]217 // not correct for checking potential deadlock...rewrite:
[ff51d87]218 $mpi_sendrecv(sendbuf, sendcount, sendtype, dest, sendtag, recvbuf, recvcount,
[d7d8b9b]219 recvtype, source, recvtag, comm, status);
[e15d0a3]220 return 0;
221}
[0a708a5]222/******************************** Collective ***********************************/
[e15d0a3]223/* Broadcasts a message from root to everyone else.
224 * Need to use a differnt comm.
225 */
226int MPI_Bcast(void *buf, int count, MPI_Datatype datatype, int root,
227 MPI_Comm comm) {
[566a657]228 int place = $mpi_comm_place(comm);
229 int nprocs = $mpi_comm_size(comm);
[323851f]230 int datatypes[1] = {(int)datatype};
[1e47fae]231 // MPI library defined collective operation checking entries:
232 $bundle checkerEntry; //the checking entry of this call
233 $bundle specEntry; //a recorded entry as specification
[1d71f60]234
[17ad6bf]235#ifndef _MPI_CONTRACT
236 $assert (_mpi_state == _MPI_INIT,
[46766eb]237 "MPI_Bcast() cannot be invoked without MPI_Init() "
238 "being called before.\n");
[17ad6bf]239#endif
[c23f74e]240 if(place == root)
241 $mpi_check_buffer(buf, count, datatype);
[e6d3df3]242 checkerEntry = $mpi_create_coroutine_entry(BCAST_TAG, root, -1, 1, datatypes);
[566a657]243 specEntry = $mpi_check_collective(comm, checkerEntry);
[e6d3df3]244 $mpi_diff_coroutine_entries(specEntry, checkerEntry, place);
[d7d8b9b]245 $mpi_bcast(buf, count, datatype, root, BCAST_TAG, comm, "MPI_Bcast()");
[e15d0a3]246 return 0;
247}
248
249/* Reduces values on all processes to a single value */
[112dfe0]250int MPI_Reduce(const void* sendbuf, void* recvbuf, int count,
[42561ab]251 MPI_Datatype datatype, MPI_Op op, int root,
252 MPI_Comm comm) {
[566a657]253 int place = $mpi_comm_place(comm);
254 int nprocs = $mpi_comm_size(comm);
[323851f]255 int datatypes[1] = {(int)datatype};
[1e47fae]256 // MPI library defined collective operation checking entries:
257 $bundle checkerEntry; //the checking entry of this call
258 $bundle specEntry; //a recorded entry as specification
[c459e50]259
[7a2dded]260#ifndef _MPI_CONTRACT
[17ad6bf]261 $assert (_mpi_state == _MPI_INIT,
[46766eb]262 "MPI_Reduce() cannot be invoked without "
263 "MPI_Init() being called before.\n");
[7a2dded]264#endif
[e6d3df3]265 checkerEntry = $mpi_create_coroutine_entry(REDUCE_TAG, root, (int)op, 1,
[d4d65d3]266 datatypes);
[566a657]267 specEntry = $mpi_check_collective(comm, checkerEntry);
[e6d3df3]268 $mpi_diff_coroutine_entries(specEntry, checkerEntry, place);
[c23f74e]269 $mpi_check_buffer(sendbuf, count, datatype);
[1888049]270 $assert(0 <= op && op <= 13, "unknown MPI reduce operation"); // refer to op.h & mpi.h in ABC/src/include for how MPI_Op is defined
[d7d8b9b]271 $mpi_reduce(sendbuf, recvbuf, count, datatype, op, root, REDUCE_TAG, comm, "MPI_Reduce()");
[e15d0a3]272 return 0;
273}
274
275/* Combines values from all processes and distributes the result back to all processes */
276/* default root is 0 */
[112dfe0]277int MPI_Allreduce(const void* sendbuf, void* recvbuf, int count,
[42561ab]278 MPI_Datatype datatype,
279 MPI_Op op, MPI_Comm comm) {
280 int root = 0;
[566a657]281 int place = $mpi_comm_place(comm);
282 int nprocs = $mpi_comm_size(comm);
[c2f38f1]283 int datatypes[1] = {(int)datatype};
[e15d0a3]284 MPI_Status status;
[1e47fae]285 // MPI library defined collective operation checking entries:
286 $bundle checkerEntry; //the checking entry of this call
287 $bundle specEntry; //a recorded entry as specification
[1d71f60]288
[7a2dded]289#ifndef _MPI_CONTRACT
[17ad6bf]290 $assert(_mpi_state == _MPI_INIT, "MPI_Allreduce() cannot be invoked without "
[3ff27cf]291 "MPI_Init() being called before.\n");
[7a2dded]292#endif
[c23f74e]293 $mpi_check_buffer(sendbuf, count, datatype);
[566a657]294 checkerEntry = $mpi_create_coroutine_entry(ALLREDUCE_TAG, root,
[d4d65d3]295 (int)op, 1, datatypes);
[566a657]296 specEntry = $mpi_check_collective(comm, checkerEntry);
[e6d3df3]297 $mpi_diff_coroutine_entries(specEntry, checkerEntry, place);
[1888049]298 $assert(0 <= op && op <= 13, "unknown MPI reduce operation"); // refer to op.h & mpi.h in ABC/src/include for how MPI_Op is defined
[ff51d87]299 $mpi_reduce(sendbuf, recvbuf, count, datatype, op, root, ALLREDUCE_TAG, comm,
[d7d8b9b]300 "MPI_Allreduce()");
[566a657]301 $mpi_bcast(recvbuf, count, datatype, root, ALLREDUCE_TAG, comm,
[d7d8b9b]302 "MPI_Allreduce()");
[e15d0a3]303 return 0;
304}
[20e1243]305
[1fbac22]306int MPI_Barrier(MPI_Comm comm){
[566a657]307 int place = $mpi_comm_place(comm);
308 int nprocs = $mpi_comm_size(comm);
[1e47fae]309 // MPI library defined collective operation checking entries:
310 $bundle checkerEntry; //the checking entry of this call
311 $bundle specEntry; //a recorded entry as specification
[1d71f60]312
[7a2dded]313#ifndef _MPI_CONTRACT
[17ad6bf]314 $assert(_mpi_state == _MPI_INIT, "MPI_Barrier() cannot be invoked "
[3ff27cf]315 "without MPI_Init() being called before.\n");
[7a2dded]316#endif
[566a657]317 checkerEntry = $mpi_create_coroutine_entry(BARRIER_TAG, 0, -1,
[1e47fae]318 0, NULL);
[566a657]319 specEntry = $mpi_check_collective(comm, checkerEntry);
[e6d3df3]320 $mpi_diff_coroutine_entries(specEntry, checkerEntry, place);
[566a657]321 $mpi_barrier(comm);
[0a708a5]322 return 0;
323}
324
325/* 1. If comm is an intracommunicator, each process (includes root process) sends the content
[566a657]326 of its send buffer to the root process. Root process receives the messages and stores
327 them in rank order
[0a708a5]328 2. TODO: If comm is an intercommunicator, it's not supported yet */
[566a657]329int MPI_Gather(const void* sendbuf, int sendcount, MPI_Datatype sendtype,
330 void* recvbuf, int recvcount, MPI_Datatype recvtype,
[0a708a5]331 int root, MPI_Comm comm){
[566a657]332 int place = $mpi_comm_place(comm);
333 int nprocs = $mpi_comm_size(comm);
[323851f]334 int datatypes[2] = {(int)sendtype, (int)recvtype};
[1e47fae]335 // MPI library defined collective operation checking entries:
336 $bundle checkerEntry; //the checking entry of this call
337 $bundle specEntry; //a recorded entry as specification
[0a708a5]338
[7a2dded]339#ifndef _MPI_CONTRACT
[17ad6bf]340 $assert(_mpi_state == _MPI_INIT, "MPI_Gather() cannot be invoked without "
[3ff27cf]341 "MPI_Init() being called before.\n");
[7a2dded]342#endif
[c69f7d3]343 if(sendbuf != MPI_IN_PLACE)
[c23f74e]344 $mpi_check_buffer(sendbuf, sendcount, sendtype);
[e6d3df3]345 checkerEntry = $mpi_create_coroutine_entry(GATHER_TAG, root, -1, 2, datatypes);
[566a657]346 specEntry = $mpi_check_collective(comm, checkerEntry);
[e6d3df3]347 $mpi_diff_coroutine_entries(specEntry, checkerEntry, place);
[ff51d87]348 $mpi_gather(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype,
[d7d8b9b]349 root, GATHER_TAG, comm, "MPI_Gather()");
[0a708a5]350 return 0;
351}
352
353/* The inverse operation of MPI_Gather() */
[566a657]354int MPI_Scatter(const void* sendbuf, int sendcount, MPI_Datatype sendtype,
[0a708a5]355 void* recvbuf, int recvcount, MPI_Datatype recvtype, int root,
356 MPI_Comm comm){
[566a657]357 int place = $mpi_comm_place(comm);
358 int nprocs = $mpi_comm_size(comm);
[be4d6aa]359 int datatypes[2] = {(int)sendtype, (int)recvtype};
[1e47fae]360 // MPI library defined collective operation checking entries:
361 $bundle checkerEntry; //the checking entry of this call
362 $bundle specEntry; //a recorded entry as specification
[0a708a5]363
[7a2dded]364#ifndef _MPI_CONTRACT
[17ad6bf]365 $assert(_mpi_state == _MPI_INIT, "MPI_Scatter() cannot be invoked without "
[3ff27cf]366 "MPI_Init() being called before.\n");
[7a2dded]367#endif
[c23f74e]368 if (place == root)
369 $mpi_check_buffer(sendbuf, sendcount, sendtype);
[566a657]370 checkerEntry = $mpi_create_coroutine_entry(SCATTER_TAG, root, -1, 2,
[d4d65d3]371 datatypes);
[566a657]372 specEntry = $mpi_check_collective(comm, checkerEntry);
[e6d3df3]373 $mpi_diff_coroutine_entries(specEntry, checkerEntry, place);
[ff51d87]374 $mpi_scatter(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype,
[d7d8b9b]375 root, SCATTER_TAG, comm, "MPI_Scatter()");
[11eac62]376 return 0;
[1fbac22]377}
[0a708a5]378
[68d54e0]379
380/* MPI_Gatherv extends the functionality of MPI_Gather by allowing a varying count of data to be sent to root process, since recvcounts is now an array.*/
[112dfe0]381int MPI_Gatherv(const void* sendbuf, int sendcount, MPI_Datatype sendtype,
382 void* recvbuf, const int recvcounts[], const int displs[],
[68d54e0]383 MPI_Datatype recvtype, int root, MPI_Comm comm){
[566a657]384 int place = $mpi_comm_place(comm);
385 int nprocs = $mpi_comm_size(comm);
[323851f]386 int datatypes[2] = {(int)sendtype, (int)recvtype};
[c23f74e]387 int recvcount = 0;
[1e47fae]388 // MPI library defined collective operation checking entries:
389 $bundle checkerEntry; //the checking entry of this call
390 $bundle specEntry; //a recorded entry as specification
[68d54e0]391
[7a2dded]392#ifndef _MPI_CONTRACT
[17ad6bf]393 $assert(_mpi_state == _MPI_INIT, "MPI_Gatherv() cannot be invoked without "
[3ff27cf]394 "MPI_Init() being called before.\n");
[7a2dded]395#endif
[c69f7d3]396 if(sendbuf != MPI_IN_PLACE)
[c23f74e]397 $mpi_check_buffer(sendbuf, sendcount, sendtype);
[566a657]398 checkerEntry = $mpi_create_coroutine_entry(GATHERV_TAG, root,
[d4d65d3]399 -1, 2, datatypes);
[566a657]400 specEntry = $mpi_check_collective(comm, checkerEntry);
[e6d3df3]401 $mpi_diff_coroutine_entries(specEntry, checkerEntry, place);
[ff51d87]402 $mpi_gatherv(sendbuf, sendcount, sendtype, recvbuf, recvcounts, displs,
[d7d8b9b]403 recvtype, root, GATHERV_TAG, comm, "MPI_Gatherv()");
[11eac62]404 return 0;
[68d54e0]405}
406
407/* MPI_Scatterv extends the functionality of MPI_Scatter by allowing a varying count of data to be sent to each process, since sendcounts is now an array.*/
[112dfe0]408int MPI_Scatterv(const void* sendbuf, const int sendcounts[], const
409 int displs[], MPI_Datatype sendtype, void* recvbuf,
[68d54e0]410 int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm){
[566a657]411 int place = $mpi_comm_place(comm);
412 int nprocs = $mpi_comm_size(comm);
[323851f]413 int datatypes[2] = {(int)sendtype, (int)recvtype};
[c23f74e]414 int sendcount = 0;
[1e47fae]415 // MPI library defined collective operation checking entries:
416 $bundle checkerEntry; //the checking entry of this call
417 $bundle specEntry; //a recorded entry as specification
[68d54e0]418
[7a2dded]419#ifndef _MPI_CONTRACT
[17ad6bf]420 $assert(_mpi_state == _MPI_INIT, "MPI_Scatterv() cannot be invoked without "
[11eac62]421 "MPI_Init() being called before.\n");
[7a2dded]422#endif
[c23f74e]423 if (place == root) {
424 for (int i = 0; i < nprocs; i++) sendcount += sendcounts[i];
425 $mpi_check_buffer(sendbuf, sendcount, sendtype);
426 }
[566a657]427 checkerEntry = $mpi_create_coroutine_entry(SCATTERV_TAG,
428 root, -1, 2,
[d4d65d3]429 datatypes);
[566a657]430 specEntry = $mpi_check_collective(comm, checkerEntry);
[e6d3df3]431 $mpi_diff_coroutine_entries(specEntry, checkerEntry, place);
[ff51d87]432 $mpi_scatterv(sendbuf, sendcounts, displs, sendtype, recvbuf,
[566a657]433 recvcount, recvtype, root, SCATTERV_TAG, comm,
[d7d8b9b]434 "MPI_Scatterv()");
[11eac62]435 return 0;
[68d54e0]436}
437
[112dfe0]438int MPI_Allgather(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
[a24137f]439 void *recvbuf, int recvcount, MPI_Datatype recvtype,
440 MPI_Comm comm){
[566a657]441 int place = $mpi_comm_place(comm);
442 int nprocs = $mpi_comm_size(comm);
[323851f]443 int datatypes[2] = {(int)sendtype, (int)recvtype};
[1e47fae]444 // MPI library defined collective operation checking entries:
445 $bundle checkerEntry; //the checking entry of this call
446 $bundle specEntry; //a recorded entry as specification
[a24137f]447
[7a2dded]448#ifndef _MPI_CONTRACT
[17ad6bf]449 $assert(_mpi_state == _MPI_INIT, "MPI_Allgather() cannot be invoked without "
[3ff27cf]450 "MPI_Init() being called before.\n");
[7a2dded]451#endif
[c69f7d3]452 if(sendbuf != MPI_IN_PLACE)
[c23f74e]453 $mpi_check_buffer(sendbuf, sendcount, sendtype);
[566a657]454 checkerEntry = $mpi_create_coroutine_entry(ALLGATHER_TAG, 0, -1, 2,
[fe9c0fe]455 datatypes);
[566a657]456 specEntry = $mpi_check_collective(comm, checkerEntry);
[e6d3df3]457 $mpi_diff_coroutine_entries(specEntry, checkerEntry, place);
[fe9c0fe]458
459 if (sendbuf != MPI_IN_PLACE)
460 $mpi_gather(sendbuf, sendcount, sendtype,
461 recvbuf, recvcount, recvtype,
462 0, ALLGATHER_TAG, comm, "MPI_Allgather()");
463 else {
464 void * in_buf = $mpi_malloc(recvcount, recvtype);
465
466 memcpy(in_buf, recvbuf + recvcount*place, sizeofDatatype(recvtype) * recvcount);
467 $mpi_gather(in_buf, recvcount, recvtype,
468 recvbuf, recvcount, recvtype,
[566a657]469 0, ALLGATHER_TAG, comm, "MPI_Allgather()");
[fe9c0fe]470 $free(in_buf);
471 }
[ff51d87]472 $mpi_bcast(recvbuf, recvcount*nprocs, recvtype, 0, ALLGATHER_TAG, comm,
[d7d8b9b]473 "MPI_Allgather()");
[a24137f]474 return 0;
475}
476
[112dfe0]477int MPI_Reduce_scatter(const void *sendbuf, void *recvbuf, const int recvcount[],
[11eac62]478 MPI_Datatype datatype, MPI_Op op, MPI_Comm comm) {
[da3b768]479 int total_count, i;
[566a657]480 int nprocs = $mpi_comm_size(comm);
481 int rank = $mpi_comm_place(comm);
[11eac62]482 int root = 0;
483 int displs[nprocs];
[323851f]484 int datatypes[1] = {(int)datatype};
[3273760]485
[1e47fae]486 // MPI library defined collective operation checking entries:
487 $bundle checkerEntry; //the checking entry of this call
488 $bundle specEntry; //a recorded entry as specification
[11eac62]489
[7a2dded]490#ifndef _MPI_CONTRACT
[17ad6bf]491 $assert(_mpi_state == _MPI_INIT, "MPI_Reduce_scatter() cannot be invoked without "
[11eac62]492 "MPI_Init() being called before.\n");
[7a2dded]493#endif
[c23f74e]494 $mpi_check_buffer(sendbuf, recvcount[rank], datatype);
[da3b768]495 for(total_count = 0, i = 0; i<nprocs; i++) {
[11eac62]496 displs[i] = total_count;
497 total_count += recvcount[i];
498 }
[566a657]499 checkerEntry = $mpi_create_coroutine_entry(RED_SCATTER_TAG, root, (int)op, 1,
[c23f74e]500 datatypes);
[566a657]501 specEntry = $mpi_check_collective(comm, checkerEntry);
[c23f74e]502 $mpi_diff_coroutine_entries(specEntry, checkerEntry, rank);
[d3a475f]503 /* Note: In MPI standard, the sendbuf and recvbuf shall not be the
504 * same, the implementation here is a lower layer helper function
505 * for MPI_Reduce routine, and the reason it plays a trick here is
506 * because allocating a memory space for a void pointer is not
507 * allowed in CIVL yet. */
[eac9892]508 void * temp = $mpi_malloc(total_count, datatype);
509
[1888049]510 $assert(0 <= op && op <= 13, "unknown MPI reduce operation"); // refer to op.h & mpi.h in ABC/src/include for how MPI_Op is defined
[566a657]511 $mpi_reduce(sendbuf, temp, total_count, datatype, op,
[d7d8b9b]512 root, RED_SCATTER_TAG, comm, "MPI_Reduce_scatter()");
[8715107]513 $mpi_scatterv(temp, recvcount, displs, datatype, recvbuf,
[178d986]514 recvcount[rank], datatype, root, RED_SCATTER_TAG, comm,
[d7d8b9b]515 "MPI_Reduce_scatter()");
[8715107]516 free(temp);
[11eac62]517 return 0;
518}
519
[112dfe0]520int MPI_Alltoall(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
[11eac62]521 void *recvbuf, int recvcount, MPI_Datatype recvtype,
522 MPI_Comm comm) {
[566a657]523 int nprocs = $mpi_comm_size(comm);
524 int rank = $mpi_comm_place(comm);
[c2f38f1]525 int root = 0;
[11eac62]526 int displs[nprocs];
527 int sendcounts[nprocs];
[323851f]528 int datatypes[2] = {(int)sendtype, (int)recvtype};
[3273760]529
[1e47fae]530 // MPI library defined collective operation checking entries:
531 $bundle checkerEntry; //the checking entry of this call
532 $bundle specEntry; //a recorded entry as specification
[11eac62]533
534 for(int i=0; i<nprocs; i++) {
535 sendcounts[i] = sendcount;
536 displs[i] = (i == 0)? 0 : (displs[i-1] + sendcount);
537 }
[7a2dded]538#ifndef _MPI_CONTRACT
[17ad6bf]539 $assert(_mpi_state == _MPI_INIT, "MPI_Alltoall() cannot be invoked without "
[11eac62]540 "MPI_Init() being called before.\n");
[7a2dded]541#endif
[c23f74e]542 $mpi_check_buffer(sendbuf, sendcount * nprocs, sendtype);
[566a657]543 checkerEntry = $mpi_create_coroutine_entry(ALLTOALL_TAG, root, -1, 2,
[d4d65d3]544 datatypes);
[566a657]545 specEntry = $mpi_check_collective(comm, checkerEntry);
[e6d3df3]546 $mpi_diff_coroutine_entries(specEntry, checkerEntry, rank);
[792d583]547 for(int i = 0; i < nprocs; i++) {
[e6d3df3]548 void * ptr = $mpi_pointer_add(recvbuf, i*sendcount, recvtype);
[792d583]549
[566a657]550 $mpi_scatterv(sendbuf, sendcounts, displs, sendtype,
[792d583]551 ptr, recvcount, recvtype, i, ALLTOALL_TAG, comm,
[d7d8b9b]552 "MPI_Alltoall()");
[792d583]553 }
[11eac62]554 return 0;
555}
556
[566a657]557int MPI_Alltoallv(const void* sendbuf, const int sendcounts[],
558 const int sdispls[], MPI_Datatype sendtype, void* recvbuf,
559 const int recvcounts[], const int rdispls[], MPI_Datatype recvtype,
[11eac62]560 MPI_Comm comm) {
[566a657]561 int nprocs = $mpi_comm_size(comm);
562 int place = $mpi_comm_place(comm);
[323851f]563 int datatypes[2] = {(int)sendtype, (int)recvtype};
[c23f74e]564 int sendcount = 0;
565 int recvcount = 0;
[1e47fae]566 // MPI library defined collective operation checking entries:
567 $bundle checkerEntry; //the checking entry of this call
568 $bundle specEntry; //a recorded entry as specification
[11eac62]569
[7a2dded]570#ifndef _MPI_CONTRACT
[17ad6bf]571 $assert(_mpi_state == _MPI_INIT, "MPI_Alltoallv() cannot be invoked without "
[11eac62]572 "MPI_Init() being called before.\n");
[7a2dded]573#endif
[c23f74e]574 for (int i = 0; i < nprocs; i++) {
575 sendcount += sendcounts[i];
576 recvcount += recvcounts[i];
577 }
578 $mpi_check_buffer(sendbuf, sendcount, sendtype);
[566a657]579 checkerEntry = $mpi_create_coroutine_entry(ALLTOALLV_TAG, 0, -1, 2,
[d4d65d3]580 datatypes);
[566a657]581 specEntry = $mpi_check_collective(comm, checkerEntry);
[e6d3df3]582 $mpi_diff_coroutine_entries(specEntry, checkerEntry, place);
[11eac62]583 for(int i = 0; i < nprocs; i++) {
[e6d3df3]584 void * ptr = $mpi_pointer_add(recvbuf, rdispls[i], recvtype);
[792d583]585
[566a657]586 $mpi_scatterv(sendbuf, sendcounts, sdispls, sendtype,
[792d583]587 ptr, recvcounts[i], recvtype, i, ALLTOALLV_TAG, comm,
[d7d8b9b]588 "MPI_Alltoallv()");
[11eac62]589 }
590 return 0;
591}
592
[566a657]593int MPI_Alltoallw(const void* sendbuf, const int sendcounts[], const int sdispls[],
[112dfe0]594 const MPI_Datatype sendtypes[], void* recvbuf,
[566a657]595 const int recvcounts[], const int rdispls[],
[112dfe0]596 const MPI_Datatype recvtypes[], MPI_Comm comm) {
[566a657]597 int nprocs = $mpi_comm_size(comm);
598 int place = $mpi_comm_place(comm);
[3273760]599 int sdispls_offset[nprocs];
[566a657]600
601 for (int i = 0; i < nprocs; i++)
[3273760]602 sdispls_offset[i] = sdispls[i] / sizeofDatatype(sendtypes[i]);
[7a2dded]603#ifndef _MPI_CONTRACT
[17ad6bf]604 $assert(_mpi_state == _MPI_INIT, "MPI_Alltoallw() cannot be invoked without "
[11eac62]605 "MPI_Init() being called before.\n");
[7a2dded]606#endif
[11eac62]607 for(int i = 0; i < nprocs; i++) {
[3273760]608 int recv_t_size = sizeofDatatype(recvtypes[i]);
609 void * ptr = $mpi_pointer_add(recvbuf, rdispls[i] / recv_t_size, recvtypes[i]);
610 void * sendptr = $mpi_pointer_add(sendbuf, sdispls_offset[i], sendtypes[i]);
[792d583]611
[c23f74e]612 $mpi_check_buffer(sendptr, sendcounts[i], sendtypes[i]);
[566a657]613 $mpi_scatterv(sendbuf, sendcounts, sdispls_offset, sendtypes[i],
614 ptr, recvcounts[i], recvtypes[i], i,
[d7d8b9b]615 ALLTOALLW_TAG, comm, "MPI_Alltoallw()");
[11eac62]616 }
617 return 0;
618}
619
[a2c8eb4]620int MPI_Scan(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype,
621 MPI_Op op, MPI_Comm comm) {
622#ifndef _MPI_CONTRACT
623 $assert(_mpi_state == _MPI_INIT, "MPI_Scan() cannot be invoked without "
624 "MPI_Init() being called before.\n");
625#endif
[566a657]626 int place = $mpi_comm_place(comm);
[a2c8eb4]627 int datatype_enum2int = (int)datatype;
628
629 // check consistency of a group of collective routine calls
[566a657]630 $bundle checkerEntry = $mpi_create_coroutine_entry(SCAN_TAG, -1, -1, 1,
[a2c8eb4]631 &datatype_enum2int);
[566a657]632 $bundle specEntry = $mpi_check_collective(comm, checkerEntry);
[a2c8eb4]633
634 $mpi_diff_coroutine_entries(specEntry, checkerEntry, place);
[566a657]635 if (sendbuf != MPI_IN_PLACE)
[a2c8eb4]636 $mpi_check_buffer(sendbuf, count, datatype);
637 $mpi_check_buffer(recvbuf, count, datatype);
638 $mpi_scan(sendbuf, recvbuf, count, datatype, op, comm);
639 return 0;
640}
641
642int MPI_Exscan(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype,
643 MPI_Op op, MPI_Comm comm) {
644#ifndef _MPI_CONTRACT
645 $assert(_mpi_state == _MPI_INIT, "MPI_Exscan() cannot be invoked without "
646 "MPI_Init() being called before.\n");
647#endif
[566a657]648 int place = $mpi_comm_place(comm);
[a2c8eb4]649 int datatype_enum2int = (int)datatype;
650
651 // check consistency of a group of collective routine calls
[566a657]652 $bundle checkerEntry = $mpi_create_coroutine_entry(EXSCAN_TAG, -1, -1, 1,
[a2c8eb4]653 &datatype_enum2int);
[566a657]654 $bundle specEntry = $mpi_check_collective(comm, checkerEntry);
[a2c8eb4]655
656 $mpi_diff_coroutine_entries(specEntry, checkerEntry, place);
657 // MPI_IN_PLACE in this routine simply means that get sendbuf from recvbuf:
[566a657]658 if (sendbuf != MPI_IN_PLACE)
[a2c8eb4]659 $mpi_check_buffer(sendbuf, count, datatype);
660 if (place > 0)
661 $mpi_check_buffer(recvbuf, count, datatype);
662 $mpi_exscan(sendbuf, recvbuf, count, datatype, op, comm);
663 return 0;
664}
665
666/* ****************** End of collecitve routines ********************* */
667
[e8f4e6a]668int MPI_Comm_dup(MPI_Comm comm, MPI_Comm * newcomm) {
[566a657]669 $scope CMPI_PROC_SCOPE = $mpi_proc_scope(comm);
[e8f4e6a]670
[7a2dded]671#ifndef _MPI_CONTRACT
[17ad6bf]672 $assert(_mpi_state == _MPI_INIT, "MPI_Comm_dup() cannot be invoked without "
[e8f4e6a]673 "MPI_Init() being called before.\n");
[7a2dded]674#endif
[ff51d87]675 $mpi_comm_dup(CMPI_PROC_SCOPE, comm, newcomm, "MPI_Comm_dup");
[e8f4e6a]676 return 0;
677}
678
679int MPI_Comm_free(MPI_Comm * comm) {
[7a2dded]680#ifndef _MPI_CONTRACT
[17ad6bf]681 $assert(_mpi_state == _MPI_INIT, "MPI_Comm_free() cannot be invoked without "
[e8f4e6a]682 "MPI_Init() being called before.\n");
[7a2dded]683#endif
[69c7880]684 $assert($is_derefable_pointer(comm), "The argument of MPI_Comm_free is NULL.");
[17ad6bf]685 $mpi_comm_free(comm, _mpi_state);
[e8f4e6a]686 return 0;
687}
688
[89addf6]689int MPI_Init_thread( int *argc, char ***argv, int required, int *provided ){
[17ad6bf]690 _mpi_state = _MPI_INIT; //TODO: why set initialized flag here ??
[89addf6]691 *provided = MPI_THREAD_MULTIPLE;
692 return MPI_SUCCESS;
693}
694
[20e1243]695#endif
Note: See TracBrowser for help on using the repository browser.