| 1 | #ifndef _ALLREDUCE_H_
|
|---|
| 2 | #define _ALLREDUCE_H_
|
|---|
| 3 |
|
|---|
| 4 | #include <mpi.h>
|
|---|
| 5 |
|
|---|
| 6 | #define uint int
|
|---|
| 7 |
|
|---|
| 8 | /****** carved out from comm ******/
|
|---|
| 9 |
|
|---|
| 10 | typedef MPI_Comm comm_ext;
|
|---|
| 11 | typedef MPI_Request comm_req;
|
|---|
| 12 |
|
|---|
| 13 | struct comm {
|
|---|
| 14 | uint id, np;
|
|---|
| 15 | comm_ext c;
|
|---|
| 16 | };
|
|---|
| 17 |
|
|---|
| 18 | /****** carved out from gs_defs ******/
|
|---|
| 19 |
|
|---|
| 20 | /* the supported domains */
|
|---|
| 21 | #define GS_FOR_EACH_DOMAIN(macro) \
|
|---|
| 22 | macro(double) \
|
|---|
| 23 | macro(float ) \
|
|---|
| 24 | macro(int ) \
|
|---|
| 25 | macro(long )
|
|---|
| 26 | // WHEN_LONG_LONG(macro(long_long))
|
|---|
| 27 |
|
|---|
| 28 | /* the supported ops */
|
|---|
| 29 | #define GS_FOR_EACH_OP(T,macro) \
|
|---|
| 30 | macro(T,add) \
|
|---|
| 31 | macro(T,mul) \
|
|---|
| 32 | macro(T,min) \
|
|---|
| 33 | macro(T,max) \
|
|---|
| 34 | macro(T,bpr)
|
|---|
| 35 |
|
|---|
| 36 | #define GS_DO_add(a,b) a+=b
|
|---|
| 37 | #define GS_DO_mul(a,b) a*=b
|
|---|
| 38 | #define GS_DO_min(a,b) if(b<a) a=b
|
|---|
| 39 | #define GS_DO_max(a,b) if(b>a) a=b
|
|---|
| 40 | #define GS_DO_bpr(a,b) \
|
|---|
| 41 | do if(b!=0) { uint a_ = a; uint b_ = b; \
|
|---|
| 42 | if(a_==0) { a=b_; break; } \
|
|---|
| 43 | for(;;) { if(a_<b_) b_>>=1; else if(b_<a_) a_>>=1; else break; } \
|
|---|
| 44 | a = a_; \
|
|---|
| 45 | } while(0)
|
|---|
| 46 |
|
|---|
| 47 | /*------------------------------------------------------------------------------
|
|---|
| 48 | Enums and constants
|
|---|
| 49 | ------------------------------------------------------------------------------*/
|
|---|
| 50 |
|
|---|
| 51 | /* domain enum */
|
|---|
| 52 | #define LIST GS_FOR_EACH_DOMAIN(ITEM) gs_dom_n
|
|---|
| 53 | #define ITEM(T) gs_##T,
|
|---|
| 54 | typedef enum { LIST } gs_dom;
|
|---|
| 55 | #undef ITEM
|
|---|
| 56 | #undef LIST
|
|---|
| 57 |
|
|---|
| 58 | /* domain type size array */
|
|---|
| 59 | #define GS_DOM_SIZE_ITEM(T) sizeof(T),
|
|---|
| 60 | #define GS_DEFINE_DOM_SIZES() \
|
|---|
| 61 | static const unsigned gs_dom_size[] = \
|
|---|
| 62 | { GS_FOR_EACH_DOMAIN(GS_DOM_SIZE_ITEM) 0 };
|
|---|
| 63 |
|
|---|
| 64 | /* operation enum */
|
|---|
| 65 | #define LIST GS_FOR_EACH_OP(T,ITEM) gs_op_n
|
|---|
| 66 | #define ITEM(T,op) gs_##op,
|
|---|
| 67 | typedef enum { LIST } gs_op;
|
|---|
| 68 | #undef ITEM
|
|---|
| 69 | #undef LIST
|
|---|
| 70 |
|
|---|
| 71 | /****** carved out from gs_local ******/
|
|---|
| 72 |
|
|---|
| 73 | #define SWITCH_DOMAIN_CASE(T) case gs_##T: WITH_DOMAIN(T); break;
|
|---|
| 74 | #define SWITCH_DOMAIN(dom) do switch(dom) { \
|
|---|
| 75 | GS_FOR_EACH_DOMAIN(SWITCH_DOMAIN_CASE) case gs_dom_n: break; } while(0)
|
|---|
| 76 |
|
|---|
| 77 | #define SWITCH_OP_CASE(T,OP) case gs_##OP: WITH_OP(T,OP); break;
|
|---|
| 78 | #define SWITCH_OP(T,op) do switch(op) { \
|
|---|
| 79 | GS_FOR_EACH_OP(T,SWITCH_OP_CASE) case gs_op_n: break; } while(0)
|
|---|
| 80 |
|
|---|
| 81 | #define DEFINE_GATHER(T,OP) \
|
|---|
| 82 | static void gather_array_##T##_##OP( \
|
|---|
| 83 | T *restrict out, const T *restrict in, uint n) \
|
|---|
| 84 | { \
|
|---|
| 85 | for(;n;--n) { T q = *in++, *p = out++; GS_DO_##OP(*p,q); } \
|
|---|
| 86 | }
|
|---|
| 87 |
|
|---|
| 88 | void gs_gather_array(void *out, const void *in, uint n, gs_dom dom, gs_op op);
|
|---|
| 89 |
|
|---|
| 90 | /************ MPI API *************/
|
|---|
| 91 | void comm_allreduce(const struct comm *com, gs_dom dom, gs_op op,
|
|---|
| 92 | void *v, uint vn, void *buf);
|
|---|
| 93 |
|
|---|
| 94 | #endif
|
|---|