23 size_t vsize = vn*gs_dom_size[
dom];
24 const uint id=com->id,
np=com->np;
25 uint n =
np, c=1, odd=0, base=0;
27 void *red = (
char*)scan+vsize;
28 buf[0]=
buffer,buf[1]=(
char*)buffer+vsize;
32 if(
id>=base+n) c|=1, base+=
n, n+=(odd&1);
37 if(c&1) n-=(odd&1), base-=n;
38 c>>=1, n<<=1, n+=(odd&1);
41 comm_irecv(&req[0],com, buf[0],vsize,
id+n/2,
id+n/2);
42 comm_isend(&req[1],com, red ,vsize,
id+n/2,
id);
46 comm_irecv(&req[0],com, scan,vsize, base,base);
56 comm_recv(com, buffer,2*vsize, base,base);
58 memcpy(red,buf[1],vsize);
62 if(
id>=base+n) c|=1, base+=
n, n+=(odd&1);
68 void *v,
uint vn,
void *buf)
70 size_t total_size = vn*gs_dom_size[
dom];
72 uint n =
np, c=1, odd=0, base=0;
76 if(
id>=base+n) c|=1, base+=
n, n+=(odd&1);
79 if(c&1) n-=(odd&1), base-=n;
80 c>>=1, n<<=1, n+=(odd&1);
83 comm_recv(com, buf,total_size,
id+n/2,
id+n/2);
97 if(
id>=base+n) c|=1, base+=
n, n+=(odd&1);
104 scan_imp(scan, com,dom,op, v,vn, buffer);
108 void *v,
uint vn,
void *buf)
113 MPI_Datatype mpitype;
115 #define DOMAIN_SWITCH() do { \
116 switch(dom) { case gs_double: mpitype=MPI_DOUBLE; break; \
117 case gs_float: mpitype=MPI_FLOAT; break; \
118 case gs_int: mpitype=MPI_INT; break; \
119 case gs_long: mpitype=MPI_LONG; break; \
120 WHEN_LONG_LONG(case gs_long_long: mpitype=MPI_LONG_LONG; break;) \
121 default: goto comm_allreduce_byhand; \
126 switch(op) {
case gs_add: mpiop=MPI_SUM;
break;
127 case gs_mul: mpiop=MPI_PROD;
break;
128 case gs_min: mpiop=MPI_MIN;
break;
129 case gs_max: mpiop=MPI_MAX;
break;
130 default:
goto comm_allreduce_byhand;
132 MPI_Allreduce(v,buf,vn,mpitype,mpiop,com->
c);
133 memcpy(v,buf,vn*gs_dom_size[dom]);
138 comm_allreduce_byhand:
152 #define SWITCH_OP_CASE(T,OP) case gs_##OP: WITH_OP(T,OP); break;
153 #define SWITCH_OP(T,op) do switch(op) { \
154 GS_FOR_EACH_OP(T,SWITCH_OP_CASE) case gs_op_n: break; } while(0)
156 #define WITH_OP(T,OP) \
157 do { T v = *in++; GS_DO_##OP(accum,v); } while(--n)
159 #define DEFINE_REDUCE(T) \
160 T PREFIXED_NAME(comm_reduce__##T)( \
161 const struct comm *comm, gs_op op, const T *in, uint n) \
163 T accum = gs_identity_##T[op], buf; \
164 if(n!=0) SWITCH_OP(T,op); \
165 comm_allreduce(comm,gs_##T,op, &accum,1, &buf); \
174 #undef SWITCH_OP_CASE
static void allreduce_imp(const struct comm *com, gs_dom dom, gs_op op, void *v, uint vn, void *buf)
static void comm_recv(const struct comm *c, void *p, size_t n, uint src, int tag)
static void comm_wait(comm_req *req, int n)
void comm_allreduce(const struct comm *com, gs_dom dom, gs_op op, void *v, uint vn, void *buf)
static void comm_send(const struct comm *c, void *p, size_t n, uint dst, int tag)
void comm_scan(void *scan, const struct comm *com, gs_dom dom, gs_op op, const void *v, uint vn, void *buffer)
double comm_dot(const struct comm *comm, double *v, double *w, uint n)
#define GS_DEFINE_IDENTITIES()
static void scan_imp(void *scan, const struct comm *com, gs_dom dom, gs_op op, const void *v, uint vn, void *buffer)
static void comm_irecv(comm_req *req, const struct comm *c, void *p, size_t n, uint src, int tag)
#define GS_FOR_EACH_DOMAIN(macro)
#define GS_DEFINE_DOM_SIZES()
establishes some macros to establish naming conventions
static void comm_isend(comm_req *req, const struct comm *c, void *p, size_t n, uint dst, int tag)