ROSS
hash-quadratic.c
Go to the documentation of this file.
1 #include <ross.h>
2 #ifdef AVL_TREE
3 #include "avl_tree.h"
4 #endif /* AVL_TREE */
5 
6 #ifndef AVL_TREE
7 static void rehash(tw_hash * hash_t, int pe);
8 static int find_entry(tw_event ** hash_t, tw_event * event, int hash_size, int pe);
9 static void insert(tw_event ** hash_t, tw_event * event, int hash_size);
10 static int find_empty(tw_event ** hash_t, tw_event * event, int hash_size);
11 static int next_prime(int ptst);
12 static tw_event **allocate_table(int hash_size);
13 static int hash_(tw_eventid event_id, int hash_size);
14 #endif
15 static int is_prime(int ptst);
16 tw_event *hash_search(tw_event ** hash_t, tw_event *evt, int size);
17 
18 void hash_print(tw_hash * h);
19 
20 static unsigned int ncpu = 1;
21 unsigned int g_tw_hash_size = 31;
22 
23 #ifndef AVL_TREE
24 int
25 hash_(tw_eventid event_id, int hash_size)
26 {
27  return event_id % hash_size;
28 }
29 #endif
30 
31 void *
33 {
34 #ifdef AVL_TREE
35  unsigned int i;
36  AvlTree avl_list;
37 
39 
41  avl_list = (AvlTree) tw_calloc(TW_LOC, "avl tree", sizeof(struct avlNode), g_tw_avl_node_count);
42 
43  for (i = 0; i < g_tw_avl_node_count - 1; i++) {
44  avl_list[i].next = &avl_list[i + 1];
45  }
46  avl_list[i].next = NULL;
47 
48  g_tw_pe->avl_list_head = &avl_list[0];
49 
50  return NULL;
51 #else
52  tw_hash *h;
53  unsigned int pi;
54 
55  ncpu = tw_nnodes();
56  h = (tw_hash *) tw_calloc(TW_LOC, "tw_hash", sizeof(tw_hash), 1);
57 
58  if (!h)
59  tw_error(TW_LOC, "Cannot allocate tw_hash.");
60 
61  h->num_stored = (int *) tw_calloc(TW_LOC, "tw_hash", sizeof(int) * ncpu, 1);
62  h->hash_sizes = (unsigned int *) tw_calloc(TW_LOC, "tw_hash", sizeof(int) * ncpu, 1);
63  h->incoming = (tw_event ***) tw_calloc(TW_LOC, "tw_hash", sizeof(tw_event *)* ncpu, 1);
64 
67 
68  for (pi = 0; pi < ncpu; pi++)
69  {
70  h->num_stored[pi] = 0;
71  h->hash_sizes[pi] = g_tw_hash_size;
72  h->incoming[pi] = allocate_table(h->hash_sizes[pi]);
73  }
74 
75  return (void *) h;
76 #endif
77 }
78 
79 void
80 tw_hash_insert(void *h, tw_event * event, long pe)
81 {
82 #ifdef AVL_TREE
83  (void) h;
84  (void) pe;
85  tw_clock start;
86 
88 
89  start = tw_clock_read();
90  avlInsert(&event->dest_lp->kp->avl_tree, event);
91  g_tw_pe->stats.s_avl += tw_clock_read() - start;
92 #else
93  tw_hash *hash_t;
94 
95  hash_t = (tw_hash *) h;
96 
97  insert(hash_t->incoming[pe], event, hash_t->hash_sizes[pe]);
98 
99  (hash_t->num_stored[pe])++;
100  if (hash_t->num_stored[pe] > floor(hash_t->hash_sizes[pe] * MAX_FRACTION))
101  {
102  rehash(hash_t, pe);
103  }
104 #endif
105 }
106 
107 #ifndef AVL_TREE
108 void
109 insert(tw_event ** hash_t, tw_event * event, int hash_size)
110 {
111  int key = 0;
112 
113  key = find_empty(hash_t, event, hash_size);
114  hash_t[key] = event;
115 }
116 
117 void
118 rehash(tw_hash * hash_t, int pe)
119 {
120  int old_size;
121  int old_stored;
122  int i;
123  tw_event **old_list;
124 
125  old_stored = hash_t->num_stored[pe];
126  old_list = hash_t->incoming[pe];
127  old_size = hash_t->hash_sizes[pe];
128 
129  hash_t->num_stored[pe] = 0;
130  hash_t->hash_sizes[pe] = next_prime(hash_t->hash_sizes[pe]);
131  hash_t->incoming[pe] = allocate_table(hash_t->hash_sizes[pe]);
132 
133  for (i = 0; i < old_size; i++)
134  {
135  if (old_list[i] != NULL)
136  {
137  insert(hash_t->incoming[pe], old_list[i], hash_t->hash_sizes[pe]);
138  (hash_t->num_stored[pe])++;
139  }
140  }
141 
142  if(old_stored != hash_t->num_stored[pe])
143  tw_error(TW_LOC, "Did not rehash properly!");
144 
145 #if VERIFY_HASH_QUAD
146  printf("\nHASH TABLE RESIZED: old size = %d, new size = %d \n\n", old_size,
147  hash_t->hash_sizes[pe]);
148 #endif
149 }
150 
151 int
152 find_empty(tw_event ** hash_t, tw_event * event, int hash_size)
153 {
154  unsigned int i;
155  int key;
156 
157  i = 0;
158  key = hash_(event->event_id, hash_size);
159 
160  if(0 > key)
161  tw_error(TW_LOC, "here!");
162 
163  while (hash_t[key])
164  {
165  key += 2 * (++i) - 1;
166  if (key >= hash_size)
167  key -= hash_size;
168  }
169 
170  return key;
171 }
172 
173 int
174 find_entry(tw_event ** hash_t, tw_event * event, int hash_size, int pe)
175 {
176  unsigned int i;
177  int key;
178 
179  i = 0;
180  key = hash_(event->event_id, hash_size);
181 
182  while (hash_t[key] == NULL || event->event_id != hash_t[key]->event_id)
183  {
184  key += 2 * (++i) - 1;
185  if (key >= hash_size)
186  key -= hash_size;
187 
188  if (key > hash_size)
189  {
190  tw_error(TW_LOC, "Cannot find event in hash table: PE %d, key %d, size %d\n",
191  pe, key, hash_size);
192  }
193  }
194 
195  return key;
196 }
197 
198 tw_event **
199 allocate_table(int hash_size)
200 {
201  return (tw_event **) tw_calloc(TW_LOC, "tw_hash", sizeof(tw_event *) * hash_size, 1);
202 }
203 #endif
204 
205 tw_event *
206 tw_hash_remove(void *h, tw_event * event, long pe)
207 {
208 #if AVL_TREE
209  (void) h;
210  (void) pe;
211  tw_event *ret;
212  tw_clock start;
213 
215 
216  start = tw_clock_read();
217  ret = avlDelete(&event->dest_lp->kp->avl_tree, event);
218  g_tw_pe->stats.s_avl += tw_clock_read() - start;
219  return ret;
220 #else
221  tw_hash *hash_t = (tw_hash *) h;
222  tw_event *ret_event;
223  int key;
224 
225  if(pe > tw_nnodes() - 1)
226  tw_error(TW_LOC, "bad pe id");
227 
228  key = find_entry(hash_t->incoming[pe], event, hash_t->hash_sizes[pe], pe);
229  ret_event = hash_t->incoming[pe][key];
230 
231  hash_t->incoming[pe][key] = NULL;
232  (hash_t->num_stored[pe])--;
233 
234  return ret_event;
235 #endif
236 }
237 
238 int
239 next_prime(int ptst)
240 {
241 
242  ptst = ptst * 2 + 1;
243 
244  if (is_prime(ptst))
245  {
246  // printf("%d is prime.\n", ptst);
247  return ptst;
248  }
249  // printf("Searching forward for next prime... ");
250  while (!is_prime(ptst))
251  ptst += 2;
252 
253  // printf("found %d.\n",ptst);
254 
255  return ptst;
256 }
257 
258 int
259 is_prime(int ptst)
260 {
261  long pmaxseek, a;
262  int prim_found;
263 
264  if (ptst % 2 == 0)
265  return 0;
266 
267  prim_found = 1;
268  pmaxseek = (long)sqrt((double)ptst) + 1;
269 
270  for (a = 3; a <= pmaxseek; a++, a++)
271  {
272  if (!(ptst % a))
273  {
274  prim_found = 0;
275  break;
276  }
277  }
278 
279  return prim_found;
280 }
281 
282 tw_event *
283 hash_search(tw_event ** hash_t, tw_event *evt, int size)
284 {
285  int j, empty;
286  tw_event *e;
287 
288  for (empty = 0, j = 0; j < size; j++)
289  {
290  e = hash_t[j];
291 
292  if (e && (e->event_id == evt->event_id))
293  {
294  printf("Found event in hash: %d\n", j);
295  return e;
296  } else
297  empty++;
298  }
299 
300  printf("%ld: HASH has %d empty cells. \n", g_tw_mynode, empty);
301 
302  return NULL;
303 }
304 
305 void
307 {
308  unsigned int i, j, empty;
309  unsigned int *sizes = h->hash_sizes;
310  int *stored = h->num_stored;
311  tw_event **hash_t;
312  tw_event *e;
313 
314  for (i = 0; i < ncpu; i++)
315  {
316  printf("PE %d: \n", i);
317  printf("table size: %d \n", sizes[i]);
318  printf("num_stored: %d \n\n", stored[i]);
319 
320  hash_t = h->incoming[i];
321 
322  for (empty = 0, j = 0; j < sizes[i]; j++)
323  {
324  e = hash_t[j];
325 
326  if (e)
327  {
328  //printf("recv_ts = %f \n", e->recv_ts);
329  //printf("%d: %ld \n\n", j, e->event_id);
330  } else
331  empty++;
332  }
333  printf("PE %d has %d empty cells. \n", i, empty);
334  }
335 }
#define TW_LOC
Definition: ross-extern.h:164
static unsigned int ncpu
void * tw_hash_create()
void avlInsert(AvlTree *t, tw_event *key)
Definition: avl_tree.c:163
tw_lp * dest_lp
Destination LP ID.
Definition: ross-types.h:280
tw_eventid event_id
Unique id assigned by src_lp->pe if remote.
Definition: ross-types.h:264
void tw_error(const char *file, int line, const char *fmt,...) NORETURN
Definition: tw-util.c:74
static int is_prime(int ptst)
tw_statistics stats
per PE counters
Definition: ross-types.h:415
AvlTree avl_tree
Definition: ross-types.h:356
int * num_stored
unsigned int g_tw_hash_size
static tw_clock tw_clock_read(void)
Definition: aarch64.h:6
tw_event * avlDelete(AvlTree *t, tw_event *key)
Definition: avl_tree.c:251
int next_prime(int ptst)
unsigned int tw_nnodes(void)
Definition: network-mpi.c:103
tw_kp * kp
kp – Kernel process that we belong to (must match pe).
Definition: ross-types.h:313
Event Stucture.
Definition: ross-types.h:250
void tw_hash_insert(void *h, tw_event *event, long pe)
tw_event *** incoming
tw_event * hash_search(tw_event **hash_t, tw_event *evt, int size)
void hash_print(tw_hash *h)
uint32_t g_tw_avl_node_count
Definition: ross-global.c:37
tw_peid g_tw_mynode
Definition: ross-global.c:88
unsigned avl_tree_size
Definition: ross-types.h:393
#define MAX_FRACTION
Definition: hash-quadratic.h:4
tw_clock s_avl
Definition: ross-types.h:148
AvlTree avl_list_head
Definition: ross-types.h:392
struct avlNode * next
Definition: avl_tree.h:11
tw_pe * g_tw_pe
Definition: ross-global.c:75
tw_pe * pe
Definition: avl_tree.c:11
uint64_t tw_clock
Definition: aarch64.h:4
struct avlNode * AvlTree
Definition: ross-types.h:21
tw_event * tw_hash_remove(void *h, tw_event *event, long pe)
void * tw_calloc(const char *file, int line, const char *for_who, size_t e_sz, size_t n)
Definition: tw-util.c:203
unsigned int tw_eventid
Definition: ross-types.h:46
unsigned int * hash_sizes