Nek5000
SEM for Incompressible NS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
comm.h
Go to the documentation of this file.
1 #ifndef COMM_H
2 #define COMM_H
3 
4 /* requires:
5  <stddef.h> for size_t
6  <stdlib.h> for exit
7  "fail.h", "types.h"
8  "gs_defs.h" for comm_allreduce, comm_scan, comm_reduce_T
9 */
10 
11 #if !defined(FAIL_H) || !defined(TYPES_H)
12 #warning "comm.h" requires "fail.h" and "types.h"
13 #endif
14 
15 /*
16  When the preprocessor macro MPI is defined, defines (very) thin wrappers
17  for the handful of used MPI routines. Alternatively, when MPI is not defined,
18  these wrappers become dummy routines suitable for a single process run.
19  No code outside of "comm.h" and "comm.c" makes use of MPI at all.
20 
21  Basic usage:
22 
23  struct comm c;
24 
25  comm_init(&c, MPI_COMM_WORLD); // initializes c using MPI_Comm_dup
26 
27  comm_free(&c);
28 
29  Very thin MPI wrappers: (see below for implementation)
30 
31  comm_send,_recv,_isend,_irecv,_time,_barrier
32 
33  Additionally, some reduction and scan routines are provided making use
34  of the definitions in "gs_defs.h" (provided this has been included first).
35 
36  Example comm_allreduce usage:
37 
38  double v[5], buf[5];
39  comm_allreduce(&c, gs_double,gs_add, v,5,buf);
40  // Computes the vector sum of v across all procs, using
41  // buf as a scratch area. Delegates to MPI_Allreduce if possible.
42 
43  Example comm_scan usage:
44 
45  long in[5], out[2][5], buf[2][5];
46  comm_scan(out, &c,gs_long,gs_add, in,5,buf);
47  // out[0] will be the vector sum of "in" across procs with ids
48  *strictly* less than this one (exclusive behavior),
49  and out[1] will be the vector sum across all procs, as would
50  be computed with comm_allreduce.
51  Note: differs from MPI_Scan which has inclusive behavior
52 
53  Example comm_reduce_double, etc. usage:
54 
55  T out, in[10];
56  out = comm_reduce_T(&c, gs_max, in, 10);
57  // out will equal the largest element of "in",
58  across all processors
59  // T can be "double", "float", "int", "long", "slong", "sint", etc.
60  as defined in "gs_defs.h"
61 
62 */
63 
64 #ifdef MPI
65 #include <mpi.h>
66 typedef MPI_Comm comm_ext;
67 typedef MPI_Request comm_req;
68 #else
69 typedef int comm_ext;
70 typedef int comm_req;
71 typedef int MPI_Fint;
72 #endif
73 
74 #define comm_allreduce PREFIXED_NAME(comm_allreduce)
75 #define comm_scan PREFIXED_NAME(comm_scan )
76 #define comm_dot PREFIXED_NAME(comm_dot )
77 
78 /* global id, np vars strictly for diagnostic messages (fail.c) */
79 #ifndef comm_gbl_id
80 #define comm_gbl_id PREFIXED_NAME(comm_gbl_id)
81 #define comm_gbl_np PREFIXED_NAME(comm_gbl_np)
83 #endif
84 
85 struct comm {
88 };
89 
90 static void comm_init(struct comm *c, comm_ext ce);
91 /* (macro) static void comm_init_check(struct comm *c, MPI_Fint ce, uint np); */
92 /* (macro) static void comm_dup(struct comm *d, const struct comm *s); */
93 static void comm_free(struct comm *c);
94 static double comm_time(void);
95 static void comm_barrier(const struct comm *c);
96 static void comm_recv(const struct comm *c, void *p, size_t n,
97  uint src, int tag);
98 static void comm_send(const struct comm *c, void *p, size_t n,
99  uint dst, int tag);
100 static void comm_irecv(comm_req *req, const struct comm *c,
101  void *p, size_t n, uint src, int tag);
102 static void comm_isend(comm_req *req, const struct comm *c,
103  void *p, size_t n, uint dst, int tag);
104 static void comm_wait(comm_req *req, int n);
105 
106 double comm_dot(const struct comm *comm, double *v, double *w, uint n);
107 
108 #ifdef GS_DEFS_H
109 void comm_allreduce(const struct comm *com, gs_dom dom, gs_op op,
110  void *v, uint vn, void *buf);
111 void comm_scan(void *scan, const struct comm *com, gs_dom dom, gs_op op,
112  const void *v, uint vn, void *buffer);
113 
114 #define DEFINE_REDUCE(T) \
115 T PREFIXED_NAME(comm_reduce__##T)( \
116  const struct comm *comm, gs_op op, const T *in, uint n); \
117 static T comm_reduce_##T(const struct comm *c, gs_op op, const T *v, uint vn) \
118 { return PREFIXED_NAME(comm_reduce__##T)(c,op,v,vn); }
120 #undef DEFINE_REDUCE
121 
122 #define comm_reduce_sint \
123  TYPE_LOCAL(comm_reduce_int,comm_reduce_long,comm_reduce_long_long)
124 #define comm_reduce_slong \
125  TYPE_GLOBAL(comm_reduce_int,comm_reduce_long,comm_reduce_long_long)
126 
127 #endif
128 
129 /*----------------------------------------------------------------------------
130  Code for static (inline) functions
131  ----------------------------------------------------------------------------*/
132 
133 static void comm_init(struct comm *c, comm_ext ce)
134 {
135 #ifdef MPI
136  int i;
137  MPI_Comm_dup(ce, &c->c);
138  MPI_Comm_rank(c->c,&i), comm_gbl_id=c->id=i;
139  MPI_Comm_size(c->c,&i), comm_gbl_np=c->np=i;
140 #else
141  c->id = 0, c->np = 1;
142 #endif
143 }
144 
145 static void comm_init_check_(struct comm *c, MPI_Fint ce, uint np,
146  const char *file, unsigned line)
147 {
148 #ifdef MPI
149  comm_init(c,MPI_Comm_f2c(ce));
150  if(c->np != np)
151  fail(1,file,line,"comm_init_check: passed P=%u, "
152  "but MPI_Comm_size gives P=%u",
153  (unsigned)np,(unsigned)c->np);
154 #else
155  comm_init(c,0);
156  if(np != 1)
157  fail(1,file,line,"comm_init_check: passed P=%u, "
158  "but not compiled with -DMPI",(unsigned)np);
159 #endif
160 }
161 #define comm_init_check(c,ce,np) comm_init_check_(c,ce,np,__FILE__,__LINE__)
162 
163 
164 static void comm_dup_(struct comm *d, const struct comm *s,
165  const char *file, unsigned line)
166 {
167  d->id = s->id, d->np = s->np;
168 #ifdef MPI
169  MPI_Comm_dup(s->c,&d->c);
170 #else
171  if(s->np!=1) fail(1,file,line,"%s not compiled with -DMPI\n",file);
172 #endif
173 }
174 #define comm_dup(d,s) comm_dup_(d,s,__FILE__,__LINE__)
175 
176 static void comm_free(struct comm *c)
177 {
178 #ifdef MPI
179  MPI_Comm_free(&c->c);
180 #endif
181 }
182 
183 static double comm_time(void)
184 {
185 #ifdef MPI
186  return MPI_Wtime();
187 #else
188  return 0;
189 #endif
190 }
191 
192 static void comm_barrier(const struct comm *c)
193 {
194 #ifdef MPI
195  MPI_Barrier(c->c);
196 #endif
197 }
198 
199 static void comm_recv(const struct comm *c, void *p, size_t n,
200  uint src, int tag)
201 {
202 #ifdef MPI
203 # ifndef MPI_STATUS_IGNORE
204  MPI_Status stat;
205  MPI_Recv(p,n,MPI_UNSIGNED_CHAR,src,tag,c->c,&stat);
206 # else
207  MPI_Recv(p,n,MPI_UNSIGNED_CHAR,src,tag,c->c,MPI_STATUS_IGNORE);
208 # endif
209 #endif
210 }
211 
212 static void comm_send(const struct comm *c, void *p, size_t n,
213  uint dst, int tag)
214 {
215 #ifdef MPI
216  MPI_Send(p,n,MPI_UNSIGNED_CHAR,dst,tag,c->c);
217 #endif
218 }
219 
220 static void comm_irecv(comm_req *req, const struct comm *c,
221  void *p, size_t n, uint src, int tag)
222 {
223 #ifdef MPI
224  MPI_Irecv(p,n,MPI_UNSIGNED_CHAR,src,tag,c->c,req);
225 #endif
226 }
227 
228 static void comm_isend(comm_req *req, const struct comm *c,
229  void *p, size_t n, uint dst, int tag)
230 {
231 #ifdef MPI
232  MPI_Isend(p,n,MPI_UNSIGNED_CHAR,dst,tag,c->c,req);
233 #endif
234 }
235 
236 static void comm_wait(comm_req *req, int n)
237 {
238 #ifdef MPI
239 # ifndef MPI_STATUSES_IGNORE
240  MPI_Status status[8];
241  while(n>=8) MPI_Waitall(8,req,status), req+=8, n-=8;
242  if(n>0) MPI_Waitall(n,req,status);
243 # else
244  MPI_Waitall(n,req,MPI_STATUSES_IGNORE);
245 # endif
246 #endif
247 }
248 
249 static void comm_bcast(const struct comm *c, void *p, size_t n, uint root)
250 {
251 #ifdef MPI
252  MPI_Bcast(p,n,MPI_UNSIGNED_CHAR,root,c->c);
253 #endif
254 }
255 
256 #endif
static void comm_barrier(const struct comm *c)
Definition: comm.h:192
#define uint
Definition: types.h:70
comm_ext c
Definition: comm.h:87
static void comm_recv(const struct comm *c, void *p, size_t n, uint src, int tag)
Definition: comm.h:199
#define comm_gbl_id
Definition: comm.h:80
void MPI_Comm
Definition: gs_test_old.c:23
n
Definition: xxt_test.m:73
static void comm_wait(comm_req *req, int n)
Definition: comm.h:236
static void comm_send(const struct comm *c, void *p, size_t n, uint dst, int tag)
Definition: comm.h:212
static double comm_time(void)
Definition: comm.h:183
Definition: comm.h:85
#define comm_allreduce
Definition: comm.h:74
#define DEFINE_REDUCE(T)
Definition: comm.c:159
static void comm_free(struct comm *c)
Definition: comm.h:176
gs_op
Definition: gs_defs.h:77
#define comm_gbl_np
Definition: comm.h:81
static void comm_bcast(const struct comm *c, void *p, size_t n, uint root)
Definition: comm.h:249
#define comm_scan
Definition: comm.h:75
int comm_req
Definition: comm.h:70
gs_dom
Definition: gs_defs.h:61
p
Definition: xxt_test2.m:1
const gs_dom dom
Definition: gs_test.c:15
int comm_ext
Definition: comm.h:69
uint np
Definition: comm.h:86
Definition: mem.h:111
for i
Definition: xxt_test.m:74
static void comm_irecv(comm_req *req, const struct comm *c, void *p, size_t n, uint src, int tag)
Definition: comm.h:220
static void comm_init_check_(struct comm *c, MPI_Fint ce, uint np, const char *file, unsigned line)
Definition: comm.h:145
int MPI_Fint
Definition: comm.h:71
uint id
Definition: comm.h:86
#define GS_FOR_EACH_DOMAIN(macro)
Definition: gs_defs.h:18
#define comm_dot
Definition: comm.h:76
static uint np
Definition: findpts_test.c:63
static void comm_init(struct comm *c, comm_ext ce)
Definition: comm.h:133
static void comm_isend(comm_req *req, const struct comm *c, void *p, size_t n, uint dst, int tag)
Definition: comm.h:228
void fail(int status, const char *file, unsigned line, const char *fmt,...)
Definition: fail.c:47
static void comm_dup_(struct comm *d, const struct comm *s, const char *file, unsigned line)
Definition: comm.h:164