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

1.23 2.0 main test-branch
Last change on this file since dfb0fef was 4d9f19e, checked in by Manchun Zheng <zmanchun@…>, 12 years ago

used linkage for libraries comm/concurrency/mpi. other libraries will be modified soon. Everything works now, except for some mpi-civl examples that use CMPI_Gcomm, which needs to be factored out to some civl-mpi library, say civlmpi.cvh.

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

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