Nek5000
SEM for Incompressible NS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
crystal.c
Go to the documentation of this file.
1 /*------------------------------------------------------------------------------
2 
3  Crystal Router
4 
5  Accomplishes all-to-all communication in log P msgs per proc
6  The routine is low-level; the format of the input/output is an
7  array of integers, consisting of a sequence of messages with format:
8 
9  target proc
10  source proc
11  m
12  integer
13  integer
14  ...
15  integer (m integers in total)
16 
17  Before crystal_router is called, the source of each message should be
18  set to this proc id; upon return from crystal_router, the target of each
19  message will be this proc id.
20 
21  Example Usage:
22 
23  struct crystal cr;
24 
25  crystal_init(&cr, &comm); // makes an internal copy of comm
26 
27  crystal.data.n = ... ; // total number of integers (not bytes!)
28  buffer_reserve(&cr.data, crystal.n * sizeof(uint));
29  ... // fill cr.data.ptr with messages
30  crystal_router(&cr);
31 
32  crystal_free(&cr);
33 
34  ----------------------------------------------------------------------------*/
35 
36 #include <stddef.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include "c99.h"
40 #include "name.h"
41 #include "fail.h"
42 #include "types.h"
43 #include "comm.h"
44 #include "mem.h"
45 
46 #define crystal_init PREFIXED_NAME(crystal_init )
47 #define crystal_free PREFIXED_NAME(crystal_free )
48 #define crystal_router PREFIXED_NAME(crystal_router)
49 
50 struct crystal {
51  struct comm comm;
53 };
54 
55 void crystal_init(struct crystal *p, const struct comm *comm)
56 {
57  comm_dup(&p->comm, comm);
58  buffer_init(&p->data,1000);
59  buffer_init(&p->work,1000);
60 }
61 
62 void crystal_free(struct crystal *p)
63 {
64  comm_free(&p->comm);
65  buffer_free(&p->data);
66  buffer_free(&p->work);
67 }
68 
69 static void uintcpy(uint *dst, const uint *src, uint n)
70 {
71  if(dst+n<=src) memcpy (dst,src,n*sizeof(uint));
72  else if(dst!=src) memmove(dst,src,n*sizeof(uint));
73 }
74 
75 static uint crystal_move(struct crystal *p, uint cutoff, int send_hi)
76 {
77  uint len, *src, *end;
78  uint *keep = p->data.ptr, *send;
79  uint n = p->data.n;
80  send = buffer_reserve(&p->work,n*sizeof(uint));
81  if(send_hi) { /* send hi, keep lo */
82  for(src=keep,end=keep+n; src<end; src+=len) {
83  len = 3 + src[2];
84  if(src[0]>=cutoff) memcpy (send,src,len*sizeof(uint)), send+=len;
85  else uintcpy(keep,src,len), keep+=len;
86  }
87  } else { /* send lo, keep hi */
88  for(src=keep,end=keep+n; src<end; src+=len) {
89  len = 3 + src[2];
90  if(src[0]< cutoff) memcpy (send,src,len*sizeof(uint)), send+=len;
91  else uintcpy(keep,src,len), keep+=len;
92  }
93  }
94  p->data.n = keep - (uint*)p->data.ptr;
95  return send - (uint*)p->work.ptr;
96 }
97 
98 static void crystal_exchange(struct crystal *p, uint send_n, uint targ,
99  int recvn, int tag)
100 {
101  comm_req req[3];
102  uint count[2] = {0,0}, sum, *recv[2];
103 
104  if(recvn)
105  comm_irecv(&req[1],&p->comm, &count[0],sizeof(uint), targ ,tag);
106  if(recvn==2)
107  comm_irecv(&req[2],&p->comm, &count[1],sizeof(uint), p->comm.id-1,tag);
108  comm_isend(&req[0],&p->comm, &send_n,sizeof(uint), targ,tag);
109  comm_wait(req,recvn+1);
110 
111  sum = p->data.n + count[0] + count[1];
112  buffer_reserve(&p->data,sum*sizeof(uint));
113  recv[0] = (uint*)p->data.ptr + p->data.n, recv[1] = recv[0] + count[0];
114  p->data.n = sum;
115 
116  if(recvn) comm_irecv(&req[1],&p->comm,
117  recv[0],count[0]*sizeof(uint), targ ,tag+1);
118  if(recvn==2) comm_irecv(&req[2],&p->comm,
119  recv[1],count[1]*sizeof(uint), p->comm.id-1,tag+1);
120  comm_isend(&req[0],&p->comm, p->work.ptr,send_n*sizeof(uint), targ,tag+1);
121  comm_wait(req,recvn+1);
122 }
123 
124 void crystal_router(struct crystal *p)
125 {
126  uint bl=0, bh, nl;
127  uint id = p->comm.id, n=p->comm.np;
128  uint send_n, targ, tag = 0;
129  int send_hi, recvn;
130  while(n>1) {
131  nl = (n+1)/2, bh = bl+nl;
132  send_hi = id<bh;
133  send_n = crystal_move(p,bh,send_hi);
134  recvn = 1, targ = n-1-(id-bl)+bl;
135  if(id==targ) targ=bh, recvn=0;
136  if(n&1 && id==bh) recvn=2;
137  crystal_exchange(p,send_n,targ,recvn,tag);
138  if(id<bh) n=nl; else n-=nl,bl=bh;
139  tag += 2;
140  }
141 }
#define uint
Definition: types.h:70
static double sum(struct xxt *data, double v, uint n, uint tag)
Definition: xxt.c:400
size_t n
Definition: mem.h:111
#define buffer_free(b)
Definition: mem.h:158
buffer work
Definition: crystal.c:52
n
Definition: xxt_test.m:73
static void comm_wait(comm_req *req, int n)
Definition: comm.h:236
#define crystal_router
Definition: crystal.c:48
#define crystal_free
Definition: crystal.c:47
#define crystal_init
Definition: crystal.c:46
Definition: comm.h:85
static void comm_free(struct comm *c)
Definition: comm.h:176
buffer data
Definition: crystal.c:52
int comm_req
Definition: comm.h:70
#define buffer_reserve(b, max)
Definition: mem.h:157
static uint crystal_move(struct crystal *p, uint cutoff, int send_hi)
Definition: crystal.c:75
p
Definition: xxt_test2.m:1
uint np
Definition: comm.h:86
Definition: mem.h:111
static void crystal_exchange(struct crystal *p, uint send_n, uint targ, int recvn, int tag)
Definition: crystal.c:98
static void comm_irecv(comm_req *req, const struct comm *c, void *p, size_t n, uint src, int tag)
Definition: comm.h:220
void * ptr
Definition: mem.h:111
#define buffer_init(b, max)
Definition: mem.h:155
static void uintcpy(uint *dst, const uint *src, uint n)
Definition: crystal.c:69
uint id
Definition: comm.h:86
#define comm_dup(d, s)
Definition: comm.h:174
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)
Definition: comm.h:228
struct comm comm
Definition: crystal.c:51