source: CIVL/text/include/mpi.cvl@ 22aa1b0

1.23 2.0 acw/focus-triggers main test-branch
Last change on this file since 22aa1b0 was 203d348, checked in by Ziqing Luo <ziqing@…>, 12 years ago

remove a junk include statement added when debugging

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

  • Property mode set to 100644
File size: 11.0 KB
Line 
1#ifdef __CIVL_MPI__
2#else
3#define __CIVL_MPI__
4
5#include <concurrency.cvh>
6#include <bundle.cvh>
7#include <mpi.h>
8#include <civlmpi.cvh>
9#include <string.h>
10
11/* Completed definition for mpi-common.h */
12struct MPI_Request{
13 int id;
14};
15
16struct MPI_Comm {
17 $comm p2p; // point-to-point communication
18 $comm col; // collective communication
19 $barrier barrier;
20 __MPI_Sys_status__ status;
21};
22
23/********************************** State *****************************************/
24/* The number of times the MPI_Wtime function has been called */
25int CMPI_time_count = 0;
26
27/************************** MPI LIB Implementations *******************************/
28double MPI_Wtime() {
29 double result = CMPI_time(CMPI_time_count);
30
31 CMPI_time_count++;
32 return result;
33}
34
35int MPI_Comm_size(MPI_Comm comm, int *size) {
36 $assert comm.status == __INIT :
37 "MPI_Comm_size() cannot be invoked without MPI_Init() being called before.\n";
38 *size = $comm_size(comm.p2p);
39 return 0;
40}
41
42int MPI_Comm_rank(MPI_Comm comm, int *rank) {
43 $assert comm.status == __INIT :
44 "MPI_Comm_rank() cannot be invoked without MPI_Init() being called before.\n";
45 *rank = $comm_place(comm.p2p);
46 return 0;
47}
48
49int MPI_Send(void *buf, int count, MPI_Datatype datatype, int dest,
50 int tag, MPI_Comm comm) {
51 $assert comm.status == __INIT :
52 "MPI_Send() cannot be invoked without MPI_Init() being called before.\n";
53 return CMPI_Send(buf, count, datatype, dest, tag, comm.p2p);
54}
55
56int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source,
57 int tag, MPI_Comm comm, MPI_Status *status) {
58 $assert comm.status == __INIT :
59 "MPI_Recv() cannot be invoked without "
60 "MPI_Init() being called before.\n";
61 return CMPI_Recv(buf, count, datatype, source, tag, comm.p2p, status);
62}
63
64int MPI_Get_count(MPI_Status *status, MPI_Datatype datatype, int *count) {
65 *count = status->size/sizeofDatatype(datatype);
66 return 0;
67}
68
69int MPI_Sendrecv(void *sendbuf, int sendcount, MPI_Datatype sendtype,
70 int dest, int sendtag,
71 void *recvbuf, int recvcount, MPI_Datatype recvtype,
72 int source, int recvtag,
73 MPI_Comm comm, MPI_Status *status) {
74 $assert comm.status == __INIT :
75 "MPI_Sendrecv() cannot be invoked "
76 "without MPI_Init() being called before.\n";
77 // not correct for checking potential deadlock...rewrite:
78 MPI_Send(sendbuf, sendcount, sendtype, dest, sendtag, comm);
79 MPI_Recv(recvbuf, recvcount, recvtype, source, recvtag, comm, status);
80 return 0;
81}
82/******************************** Collective ***********************************/
83/* Broadcasts a message from root to everyone else.
84 * Need to use a differnt comm.
85 */
86int MPI_Bcast(void *buf, int count, MPI_Datatype datatype, int root,
87 MPI_Comm comm) {
88 $assert comm.status == __INIT :
89 "MPI_Bcast() cannot be invoked without MPI_Init() "
90 "being called before.\n";
91 if ($comm_place(comm.col) == root) {
92 int nprocs = $comm_size(comm.col);
93
94 for (int i=0; i<nprocs; i++)
95 if (i != root)
96 CMPI_Send(buf, count, datatype, i, BCAST_TAG, comm.col);
97 } else {
98 CMPI_Recv(buf, count, datatype, root, BCAST_TAG, comm.col,
99 MPI_STATUS_IGNORE);
100 }
101 return 0;
102}
103
104/* Reduces values on all processes to a single value */
105int MPI_Reduce(const void* sendbuf, void* recvbuf, int count,
106 MPI_Datatype datatype, MPI_Op op, int root,
107 MPI_Comm comm) {
108 int rank;
109
110 $assert comm.status == __INIT :
111 "MPI_Reduce() cannot be invoked without "
112 "MPI_Init() being called before.\n";
113 rank = $comm_place(comm.col);
114 if (rank != root)
115 CMPI_Send(sendbuf, count, datatype, root, REDUCE_TAG, comm.col);
116 else {
117 int nprocs = $comm_size(comm.col);
118 int size;
119
120 size = count * sizeofDatatype(datatype);
121 for (int i = 0; i<nprocs; i++) {
122 if(i == root)
123 memcpy(recvbuf, sendbuf, size);
124 else{
125 $message in = $comm_dequeue(comm.col, i, REDUCE_TAG);
126
127 /* the third argument "count" indicates the number of cells needs doing the
128 operation. */
129 $bundle_unpack_apply(in.data, recvbuf, count, op);
130 $assert in.size <= size :
131 "Message of size %d exceeds the specified size %d.", in.size, size;
132 }
133 }
134 }
135 return 0;
136}
137
138/* Combines values from all processes and distributes the result back to all processes */
139/* default root is 0 */
140int MPI_Allreduce(const void* sendbuf, void* recvbuf, int count,
141 MPI_Datatype datatype,
142 MPI_Op op, MPI_Comm comm) {
143 int root = 0;
144 MPI_Status status;
145
146 $assert comm.status == __INIT :
147 "MPI_Allreduce() cannot be invoked without "
148 "MPI_Init() being called before.\n";
149 MPI_Reduce(sendbuf, recvbuf, count, datatype, op, root, comm);
150 MPI_Bcast(recvbuf, count, datatype, root, comm);
151 return 0;
152}
153
154int MPI_Barrier(MPI_Comm comm){
155 $assert comm.status == __INIT : "MPI_Allreduce() cannot be invoked without MPI_Init() being called before.\n";
156 $barrier_call(comm.barrier);
157 return 0;
158}
159
160/* 1. If comm is an intracommunicator, each process (includes root process) sends the content
161 of its send buffer to the root process. Root process receives the messages and stores
162 them in rank order
163 2. TODO: If comm is an intercommunicator, it's not supported yet */
164int MPI_Gather(const void* sendbuf, int sendcount, MPI_Datatype sendtype,
165 void* recvbuf, int recvcount, MPI_Datatype recvtype,
166 int root, MPI_Comm comm){
167 int rank, nprocs;
168 _Bool rootInPlace = $false;
169 MPI_Status status;
170
171 $assert comm.status == __INIT :
172 "MPI_Gather() cannot be invoked without "
173 "MPI_Init() being called before.\n";
174 rank = $comm_place(comm.col);
175 nprocs = $comm_size(comm.col);
176 if(sendbuf == MPI_IN_PLACE){// Sendbuf is ignored at root
177 $assert root == rank:
178 "Only root can replace 'sendbuf' with 'MPI_IN_PLACE'.";
179 rootInPlace = $true;
180 }
181 else
182 MPI_Send(sendbuf, sendcount, sendtype, root, GATHER_TAG, comm);
183 // sendbuf cannot be ignored
184 if(rank == root){
185 int real_recvcount;
186 int offset;
187
188 // For root process, check if sendtype is equal to
189 // recvtype which is required by MPI standard.
190 $assert sendtype == recvtype :
191 "MPI_Gather() asks for equality "
192 "between 'sendtype' and 'recvtype'.";
193 for(int i=0; i<nprocs; i++){
194 // Since currently we don't support pointer addition
195 // on non-array type obejcts, we don't need
196 // to care about datatype extent.
197 offset = i * recvcount;
198 //If optional ignorance not used or it's not at root iteration, then we do MPI_Send()
199 if(!rootInPlace || i != root) {
200 MPI_Recv(recvbuf + offset, recvcount, recvtype, i, GATHER_TAG, comm, &status);
201 MPI_Get_count(&status, recvtype, &real_recvcount);
202 $assert real_recvcount == recvcount :
203 "MPI_Gather() asks for equality between"
204 " the amount of data sent and the "
205 "amount of data received.";
206 }
207 }
208 }
209 return 0;
210}
211
212/* The inverse operation of MPI_Gather() */
213int MPI_Scatter(const void* sendbuf, int sendcount, MPI_Datatype sendtype,
214 void* recvbuf, int recvcount, MPI_Datatype recvtype, int root,
215 MPI_Comm comm){
216 int rank, nprocs;
217 _Bool rootInPlace = $false;
218
219 $assert comm.status == __INIT :
220 "MPI_Scatter() cannot be invoked without "
221 "MPI_Init() being called before.\n";
222 rank = $comm_place(comm.col);
223 nprocs = $comm_size(comm.col);
224 if(recvbuf == MPI_IN_PLACE){// Sendbuf is ignored at root
225 $assert root == rank:
226 "Only root can replace 'recvbuf' with 'MPI_IN_PLACE'.";
227 rootInPlace = $true;
228 }
229 if(rank == root){
230 int offset;
231
232 // For root process, check if sendtype is equal to
233 // recvtype which is required by MPI standard.
234 $assert sendtype == recvtype :
235 "MPI_Scatter() asks for equality "
236 "between 'sendtype' and 'recvtype'.";
237 for(int i=0; i<nprocs; i++){
238 offset = i * sendcount;
239 if(!rootInPlace || i != root)
240 MPI_Send(sendbuf + offset, sendcount, sendtype, i, SCATTER_TAG, comm);
241 }
242 }
243 if(!rootInPlace){//Already checked that (rootInPlace == true)==>(root==rank)
244 int real_recvcount;
245 MPI_Status status;
246
247 MPI_Recv(recvbuf, recvcount, recvtype, root, SCATTER_TAG, comm, &status);
248 MPI_Get_count(&status, recvtype, &real_recvcount);
249 $assert real_recvcount == recvcount :
250 "MPI_Gather() asks for equality between"
251 " the amount of data sent and the "
252 "amount of data received.";
253 }
254}
255
256
257/* 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.*/
258int MPI_Gatherv(const void* sendbuf, int sendcount, MPI_Datatype sendtype,
259 void* recvbuf, const int recvcounts[], const int displs[],
260 MPI_Datatype recvtype, int root, MPI_Comm comm){
261 int rank, nprocs;
262 _Bool rootInPlace = $false;
263
264 $assert comm.status == __INIT :
265 "MPI_Gatherv() cannot be invoked without "
266 "MPI_Init() being called before.\n";
267 rank = $comm_place(comm.col);
268 nprocs = $comm_size(comm.col);
269 if(sendbuf == MPI_IN_PLACE){
270 $assert root == rank:
271 "Only root can replace 'sendbuf' with 'MPI_IN_PLACE'.";
272 rootInPlace = $true;
273 }else{
274 MPI_Send(sendbuf, sendcount, sendtype, root, GATHERV_TAG, comm);
275 }
276 //Root receive
277 if(rank == root){
278 int real_recvcount;
279 MPI_Status status;
280
281 $assert sendtype == recvtype :
282 "MPI_Gatherv() asks for equality "
283 "between 'sendtype' and 'recvtype'.";
284 for(int i=0; i<nprocs; i++){
285 if(!rootInPlace || i != root){
286 MPI_Recv(recvbuf + displs[i], recvcounts[i], recvtype, i, GATHERV_TAG, comm, &status);
287 MPI_Get_count(&status, recvtype, &real_recvcount);
288 $assert real_recvcount == recvcounts[i] :
289 "MPI_Gatherv() asks for equality between"
290 " the amount of data sent and the "
291 "amount of data received.";
292 }
293 }
294 }
295}
296
297/* 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.*/
298int MPI_Scatterv(const void* sendbuf, const int sendcounts[], const
299 int displs[], MPI_Datatype sendtype, void* recvbuf,
300 int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm){
301 int rank, nprocs;
302 _Bool rootInPlace = $false;
303
304 $assert comm.status == __INIT :
305 "MPI_Scatterv() cannot be invoked without "
306 "MPI_Init() being called before.\n";
307 rank = $comm_place(comm.col);
308 nprocs = $comm_size(comm.col);
309 if(recvbuf == MPI_IN_PLACE){
310 $assert root == rank:
311 "Only root can replace 'recvbuf' with 'MPI_IN_PLACE'.";
312 rootInPlace = $true;
313 }
314 if(rank == root){
315 //For process root, check sendtype and recvtype
316 $assert sendtype == recvtype :
317 "MPI_Scatterv() asks for equality "
318 "between 'sendtype' and 'recvtype'.";
319
320 for(int i=0; i<nprocs; i++){
321 if(!rootInPlace || i != root)
322 MPI_Send(sendbuf + displs[i], sendcounts[i], sendtype, i,
323 SCATTERV_TAG, comm);
324 }
325 }
326 if(!rootInPlace){
327 MPI_Status status;
328 int real_recvcount;
329
330 MPI_Recv(recvbuf, recvcount, recvtype, root, SCATTERV_TAG, comm, &status);
331 MPI_Get_count(&status, recvtype, &real_recvcount);
332 $assert real_recvcount == recvcount :
333 "Process rank:%d\nMPI_Scatterv() asks for equality between"
334 " the amount of data sent (%d) and the "
335 "amount of data received (%d).", rank, real_recvcount, recvcount;
336 }
337}
338
339#endif
Note: See TracBrowser for help on using the repository browser.