source: CIVL/text/include/mpi.cvl@ c2a3f74

1.23 2.0 main test-branch
Last change on this file since c2a3f74 was c2a3f74, checked in by Ziqing Luo <ziqing@…>, 12 years ago

changed the implementation of MPI_Reduce

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

  • Property mode set to 100644
File size: 7.4 KB
RevLine 
[1fbac22]1#ifndef __MPI_CVL__
[20e1243]2#define __MPI_CVL__
[411e0b8]3//TODO make a Datatype struct, which has a field "int size;" Define one of these objects for MPI_INT, MPI_DOUBLE, etc.
4//TODO Then provide methods like MPI provides for creating new ones.
5//TODO then support MPI_Type_contig(datatype, int n).
6
[1fbac22]7#define BCAST_TAG 999
8#define REDUCE_TAG 998
9
10/* Completed definition for mpi-common.h */
11struct MPI_Status{
12 int MPI_SOURCE;
13 int MPI_TAG;
14 int MPI_ERROR;
15 int size;
16};
17
18/* Definition of CIVL-MPI */
19typedef enum {
20 __UNINIT,
21 __INIT,
22 __FINALIZED
23}__MPI_Sys_status__;
24
25struct MPI_Request{
26 int id;
27};
28
[20e1243]29/* Definition of CMPI_Gcomm and MPI_Comm */
[1fbac22]30typedef struct CMPI_Gcomm {
[20e1243]31 $gcomm p2p; // point-to-point communication
32 $gcomm col; // collective communication
[1fbac22]33 $gbarrier gbarrier;
34} CMPI_Gcomm;
[20e1243]35
36struct MPI_Comm {
37 $comm p2p; // point-to-point communication
38 $comm col; // collective communication
[1fbac22]39 $barrier barrier;
40 __MPI_Sys_status__ status;
[20e1243]41};
42
[2e6fe6f]43/********************************** State **************************************/
44
45/* The number of times the MPI_Wtime function has been called */
46int CMPI_time_count = 0;
47
[e15d0a3]48/****************************** Helper Functions **********************************/
49int sizeofDatatype(MPI_Datatype datatype) {
50 switch (datatype) {
51 case MPI_INT:
52 return sizeof(int);
53 case MPI_FLOAT:
54 return sizeof(float);
55 case MPI_DOUBLE:
56 return sizeof(double);
57 case MPI_CHAR:
58 return sizeof(char);
59 default:
60 $assert(0, "Unreachable");
61 }
62}
63
64/************************** MPI LIB Implementations *******************************/
[2e6fe6f]65
66$abstract double CMPI_time(int count);
67
68double MPI_Wtime() {
69 double result = CMPI_time(CMPI_time_count);
70
71 CMPI_time_count++;
72 return result;
73}
74
[e15d0a3]75CMPI_Gcomm CMPI_Gcomm_create($scope scope, int size) {
76 CMPI_Gcomm result;
77
78 result.p2p = $gcomm_create(scope, size);
79 result.col = $gcomm_create(scope, size);
[1fbac22]80 result.gbarrier = $gbarrier_create(scope, size);
[e15d0a3]81 return result;
82}
83
84void CMPI_Gcomm_destroy(CMPI_Gcomm gc) {
85 $gcomm_destroy(gc.p2p);
86 $gcomm_destroy(gc.col);
[1fbac22]87 $gbarrier_destroy(gc.gbarrier);
[e15d0a3]88}
89
[1fbac22]90MPI_Comm CMPI_Comm_create($scope scope, CMPI_Gcomm gc, int rank) {
[e15d0a3]91 MPI_Comm result;
92
93 result.p2p = $comm_create(scope, gc.p2p, rank);
94 result.col = $comm_create(scope, gc.col, rank);
[1fbac22]95 result.barrier = $barrier_create(scope, gc.gbarrier, rank);
[c574547]96 result.status = __UNINIT;
[e15d0a3]97 return result;
98}
99
[1fbac22]100void CMPI_Comm_destroy(MPI_Comm comm) {
[e15d0a3]101 $comm_destroy(comm.p2p);
102 $comm_destroy(comm.col);
[1fbac22]103 $barrier_destroy(comm.barrier);
[e15d0a3]104}
105
[c574547]106int __MPI_Init(MPI_Comm *comm) {
107 comm->status = __INIT;
[e15d0a3]108 return 0;
109}
110
[c574547]111int __MPI_Finalize(MPI_Comm *comm) {
112 comm->status = __FINALIZED;
[e15d0a3]113 return 0;
114}
115
116int MPI_Comm_size(MPI_Comm comm, int *size) {
[411e0b8]117 $assert(comm.status == __INIT, "MPI_Comm_size() cannot be invoked without MPI_Init() being called before.\n");
[e15d0a3]118 *size = $comm_size(comm.p2p);
119 return 0;
120}
121
122int MPI_Comm_rank(MPI_Comm comm, int *rank) {
[411e0b8]123 $assert(comm.status == __INIT, "MPI_Comm_rank() cannot be invoked without MPI_Init() being called before.\n");
[e15d0a3]124 *rank = $comm_place(comm.p2p);
125 return 0;
126}
127
128
129int CMPI_Send(void *buf, int count, MPI_Datatype datatype, int dest,
130 int tag, $comm comm) {
131 if (dest >= 0) {
132 int size = count*sizeofDatatype(datatype);
133 int place = $comm_place(comm);
134 $message out = $message_pack(place, dest, tag, buf, size);
135 $comm_enqueue(comm, out);
136 }
137 return 0;
138}
139
140int MPI_Send(void *buf, int count, MPI_Datatype datatype, int dest,
141 int tag, MPI_Comm comm) {
[411e0b8]142 $assert(comm.status == __INIT, "MPI_Send() cannot be invoked without MPI_Init() being called before.\n");
[e15d0a3]143 return CMPI_Send(buf, count, datatype, dest, tag, comm.p2p);
144}
145
146
147int CMPI_Recv(void *buf, int count, MPI_Datatype datatype, int source,
148 int tag, $comm comm, MPI_Status *status) {
[42561ab]149 if (source >= 0 || source == MPI_ANY_SOURCE) {
[e15d0a3]150 $message in = $comm_dequeue(comm, source, tag);
151 int size = count*sizeofDatatype(datatype);
152
153 $message_unpack(in, buf, size);
154 if (status != MPI_STATUS_IGNORE) {
155 status->size = $message_size(in);
156 status->MPI_SOURCE = $message_source(in);
157 status->MPI_TAG = $message_tag(in);
158 status->MPI_ERROR = 0;
159 }
160 }
161 return 0;
162}
163
164int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source,
165 int tag, MPI_Comm comm, MPI_Status *status) {
[42561ab]166 $assert(comm.status == __INIT,
167 "MPI_Recv() cannot be invoked without "
168 "MPI_Init() being called before.\n");
[e15d0a3]169 return CMPI_Recv(buf, count, datatype, source, tag, comm.p2p, status);
170}
171
172int MPI_Get_count(MPI_Status *status, MPI_Datatype datatype, int *count) {
173 *count = status->size/sizeofDatatype(datatype);
174 return 0;
175}
176
177int MPI_Sendrecv(void *sendbuf, int sendcount, MPI_Datatype sendtype,
178 int dest, int sendtag,
179 void *recvbuf, int recvcount, MPI_Datatype recvtype,
180 int source, int recvtag,
181 MPI_Comm comm, MPI_Status *status) {
[42561ab]182 $assert(comm.status == __INIT,
183 "MPI_Sendrecv() cannot be invoked "
184 "without MPI_Init() being called before.\n");
185 // not correct for checking potential deadlock...rewrite:
[e15d0a3]186 MPI_Send(sendbuf, sendcount, sendtype, dest, sendtag, comm);
187 MPI_Recv(recvbuf, recvcount, recvtype, source, recvtag, comm, status);
188 return 0;
189}
190
191/* Broadcasts a message from root to everyone else.
192 * Need to use a differnt comm.
193 */
194int MPI_Bcast(void *buf, int count, MPI_Datatype datatype, int root,
195 MPI_Comm comm) {
[42561ab]196 $assert(comm.status == __INIT,
197 "MPI_Bcast() cannot be invoked without MPI_Init() "
198 "being called before.\n");
199 if ($comm_place(comm.col) == root) {
[e15d0a3]200 int nprocs = $comm_size(comm.col);
201
202 for (int i=0; i<nprocs; i++)
203 if (i != root)
204 CMPI_Send(buf, count, datatype, i, BCAST_TAG, comm.col);
205 } else {
206 CMPI_Recv(buf, count, datatype, root, BCAST_TAG, comm.col,
[42561ab]207 MPI_STATUS_IGNORE);
[e15d0a3]208 }
209 return 0;
210}
211
212/* Reduces values on all processes to a single value */
[42561ab]213int MPI_Reduce(void* sendbuf, void* recvbuf, int count,
214 MPI_Datatype datatype, MPI_Op op, int root,
215 MPI_Comm comm) {
[c459e50]216 int rank;
217
[42561ab]218 $assert(comm.status == __INIT,
219 "MPI_Reduce() cannot be invoked without "
220 "MPI_Init() being called before.\n");
[c459e50]221 rank = $comm_place(comm.col);
222 if (rank != root)
223 CMPI_Send(sendbuf, count, datatype, root, REDUCE_TAG, comm.col);
224 else {
[42561ab]225 int nprocs = $comm_size(comm.col);
[c459e50]226 int size;
[52f4a4b]227
[42561ab]228 for (int i = 0; i<nprocs; i++) {
[c459e50]229 if(i == root) continue;
230 else{
231 $message in = $comm_dequeue(comm.col, i, REDUCE_TAG);
232 size = count * sizeofDatatype(datatype);
233
234 /* the third argument "count" indicates the number of cells needs doing the
235 operation. */
236 $bundle_unpack_apply(in.data, sendbuf, count, op);
237 $assert(in.size <= size,
238 "Message of size %d exceeds the specified size %d.",
239 in.size, size);
240 }
[e15d0a3]241 }
[c459e50]242 size = count * sizeofDatatype(datatype);
243 memcpy(recvbuf, sendbuf, size);
[e15d0a3]244 }
245 return 0;
246}
247
248/* Combines values from all processes and distributes the result back to all processes */
249/* default root is 0 */
[42561ab]250int MPI_Allreduce(void* sendbuf, void* recvbuf, int count,
251 MPI_Datatype datatype,
252 MPI_Op op, MPI_Comm comm) {
253 int root = 0;
[e15d0a3]254 MPI_Status status;
[74e1869]255
[42561ab]256 $assert(comm.status == __INIT,
257 "MPI_Allreduce() cannot be invoked without "
258 "MPI_Init() being called before.\n");
[1fbac22]259 MPI_Reduce(sendbuf, recvbuf, count, datatype, op, root, comm);
260 MPI_Bcast(recvbuf, count, datatype, root, comm);
[e15d0a3]261 return 0;
262}
[20e1243]263
[1fbac22]264int MPI_Barrier(MPI_Comm comm){
265
266 $assert(comm.status == __INIT, "MPI_Allreduce() cannot be invoked without MPI_Init() being called before.\n");
267 $barrier_call(comm.barrier);
268}
[20e1243]269#endif
Note: See TracBrowser for help on using the repository browser.