MP-Gadget  5.0.1.dev1-76bc7d4726-dirty
Classes | Functions
test_mpsort.c File Reference
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>
#include <stdio.h>
#include "stub.h"
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
#include <mpi.h>
#include "../utils/endrun.h"
#include "../utils/mymalloc.h"
#include "../utils/mpsort.h"
Include dependency graph for test_mpsort.c:

Go to the source code of this file.

Classes

struct  BaseGroup
 

Functions

static void radix_int (const void *ptr, void *radix, void *arg)
 
static int64_t checksum (int64_t *data, size_t localsize, MPI_Comm comm)
 
static void generate (int64_t *data, size_t localsize, int bits, int seed)
 
static void check_sorted (void *data, int elsize, size_t localsize, int compar(void *d1, void *d2), MPI_Comm comm)
 
int compar_int (void *d1, void *d2)
 
static void do_mpsort_test (int64_t srcsize, int bits, int staggered, int gather)
 
static void fof_radix_Group_TotalCountTaskDiffMinID (const void *a, void *radix, void *arg)
 
int compar_bg (void *d1, void *d2)
 
static uint64_t checksum_minid (struct BaseGroup *data, size_t localsize, MPI_Comm comm)
 
static void do_long_radix_test (int srcsize)
 
static void test_basegroup (void **state)
 
static void test_mpsort_bits (void **state)
 
static void test_mpsort_stagger (void **state)
 
static void test_mpsort_gather (void **state)
 
int main (void)
 

Function Documentation

◆ check_sorted()

static void check_sorted ( void *  data,
int  elsize,
size_t  localsize,
int   comparvoid *d1, void *d2,
MPI_Comm  comm 
)
static

Definition at line 58 of file test_mpsort.c.

59 {
60  size_t i;
61  int ThisTask, NTask;
62  MPI_Comm_rank(comm, &ThisTask);
63  MPI_Comm_size(comm, &NTask);
64 
65  const int TAG = 0xbeef;
66 
67  for(i = 1; i < localsize; i ++) {
68  if(compar(data + i*elsize, data + (i - 1)*elsize) < 0) {
69 // struct BaseGroup * i1 = ((struct BaseGroup *)data) + i;
70 // struct BaseGroup * i2= ((struct BaseGroup *)data) +(i-1);
71 // message(1, "cur=(%ld %ld %ld) prev= (%ld %ld %ld)\n", labs(i1->OriginalTask - i1->MinIDTask), i1->MinID, i1->Length, labs(i2->OriginalTask - i2->MinIDTask), i2->MinID, i2->Length);
72  endrun(12, "Ordering of local array is broken i=%ld, d=%ld d-1=%ld. \n", i, ((int64_t *)data)[i], ((int64_t *)data)[i-1]);
73  }
74  assert_true(compar(data + i*elsize, data + (i - 1)*elsize) >=0);
75  }
76 
77  if(NTask == 1) return;
78 
79  char * prev = ta_malloc("prev", char, elsize);
80  memset(prev, -1000000, elsize);
81 
82  while(1) {
83  if(ThisTask == 0) {
84  void * ptr = prev;
85  if(localsize > 0) {
86  ptr = data + elsize * (localsize - 1);
87  }
88  MPI_Send(ptr, elsize, MPI_BYTE, ThisTask + 1, TAG, comm);
89  break;
90  }
91  if(ThisTask == NTask - 1) {
92  MPI_Recv(prev, elsize, MPI_BYTE,
93  ThisTask - 1, TAG, comm, MPI_STATUS_IGNORE);
94  break;
95  }
96  /* else */
97  if(localsize == 0) {
98  /* simply pass through whatever we get */
99  MPI_Recv(prev, elsize, MPI_BYTE, ThisTask - 1, TAG, comm, MPI_STATUS_IGNORE);
100  MPI_Send(prev, elsize, MPI_BYTE, ThisTask + 1, TAG, comm);
101  break;
102  }
103  else
104  {
105  MPI_Sendrecv(
106  data+(localsize - 1)*elsize, elsize, MPI_BYTE,
107  ThisTask + 1, TAG,
108  prev, elsize, MPI_BYTE,
109  ThisTask - 1, TAG, comm, MPI_STATUS_IGNORE);
110  break;
111  }
112  }
113 
114  if(ThisTask > 1) {
115  if(localsize > 0) {
116 // printf("ThisTask = %d prev = %d\n", ThisTask, prev);
117  if(compar(prev, data) > 0) {
118  endrun(12, "Ordering of global array is broken prev=%ld d=%ld (comp: %d). \n", prev, *(int64_t *)data, compar(prev, data));
119  }
120  assert_true(compar(prev, data) <= 0);
121  }
122  }
123 }
void endrun(int where, const char *fmt,...)
Definition: endrun.c:147
#define ta_malloc(name, type, nele)
Definition: mymalloc.h:25
int ThisTask
Definition: test_exchange.c:23
int NTask
Definition: test_exchange.c:23

References endrun(), NTask, ta_malloc, and ThisTask.

Referenced by do_long_radix_test(), and do_mpsort_test().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ checksum()

static int64_t checksum ( int64_t *  data,
size_t  localsize,
MPI_Comm  comm 
)
static

Definition at line 32 of file test_mpsort.c.

33 {
34  int64_t sum = 0;
35  size_t i;
36  for(i = 0; i < localsize; i ++) {
37  sum += data[i];
38  }
39 
40  MPI_Allreduce(MPI_IN_PLACE, &sum, 1, MPI_LONG, MPI_SUM, comm);
41  return sum;
42 }

Referenced by do_mpsort_test().

Here is the caller graph for this function:

◆ checksum_minid()

static uint64_t checksum_minid ( struct BaseGroup data,
size_t  localsize,
MPI_Comm  comm 
)
static

Definition at line 239 of file test_mpsort.c.

240 {
241  uint64_t sum = 0;
242  size_t i;
243  for(i = 0; i < localsize; i ++) {
244  sum += data[i].MinID;
245  }
246 
247  MPI_Allreduce(MPI_IN_PLACE, &sum, 1, MPI_LONG, MPI_SUM, comm);
248  return sum;
249 }
MyIDType MinID
Definition: fof.h:18

References BaseGroup::MinID.

Referenced by do_long_radix_test().

Here is the caller graph for this function:

◆ compar_bg()

int compar_bg ( void *  d1,
void *  d2 
)

Definition at line 216 of file test_mpsort.c.

217 {
218  struct BaseGroup * i1 = d1;
219  struct BaseGroup * i2 = d2;
220  int dist1 = labs(i1->OriginalTask - i1->MinIDTask);
221  int dist2 = labs(i2->OriginalTask - i2->MinIDTask);
222  /* Note reversed sign! We want the largest groups first.*/
223  if(i1->Length < i2->Length)
224  return 1;
225  else if(i1->Length > i2->Length)
226  return -1;
227  if(i1->MinID < i2->MinID)
228  return -1;
229  else if(i1->MinID > i2->MinID)
230  return 1;
231  else if(dist1 < dist2)
232  return -1;
233  else if(dist1 > dist2)
234  return 1;
235  return 0;
236 }
Definition: fof.h:13
int Length
Definition: fof.h:16
int OriginalTask
Definition: fof.h:14
int MinIDTask
Definition: fof.h:19

References BaseGroup::Length, BaseGroup::MinID, BaseGroup::MinIDTask, and BaseGroup::OriginalTask.

Referenced by do_long_radix_test().

Here is the caller graph for this function:

◆ compar_int()

int compar_int ( void *  d1,
void *  d2 
)

Definition at line 125 of file test_mpsort.c.

126 {
127  int64_t * i1 = d1;
128  int64_t * i2 = d2;
129  if(*i1 < *i2)
130  return -1;
131  else if(*i1 == *i2)
132  return 0;
133  else
134  return 1;
135 }

Referenced by do_mpsort_test().

Here is the caller graph for this function:

◆ do_long_radix_test()

static void do_long_radix_test ( int  srcsize)
static

Definition at line 253 of file test_mpsort.c.

254 {
255  int ThisTask;
256  int NTask;
257 
258  MPI_Comm_size(MPI_COMM_WORLD, &NTask);
259  MPI_Comm_rank(MPI_COMM_WORLD, &ThisTask);
260 
261  struct BaseGroup * base = mymalloc("base", srcsize * sizeof(struct BaseGroup));
262 
263  int i;
264  for(i = 0; i < srcsize; i++)
265  {
266  base[i].OriginalTask = ThisTask; /* original task */
267  base[i].MinIDTask = random() % NTask;
268  base[i].MinID = random();
269  base[i].Length = 10;
270  }
271 
272  int64_t srcsum = checksum_minid(base, srcsize, MPI_COMM_WORLD);
273  {
274  double start = MPI_Wtime();
275 
276  mpsort_mpi_newarray(base, srcsize,
277  base, srcsize,
278  sizeof(struct BaseGroup),
280  MPI_COMM_WORLD);
281 
282  MPI_Barrier(MPI_COMM_WORLD);
283  double end = MPI_Wtime();
284 
285  int64_t destsum = checksum_minid(base, srcsize, MPI_COMM_WORLD);
286 
287  if(destsum != srcsum) {
288  endrun(5, "MPSort checksum is inconsistent.\n");
289  MPI_Abort(MPI_COMM_WORLD, -1);
290  }
291 
292  check_sorted(base, sizeof(struct BaseGroup), srcsize, compar_bg, MPI_COMM_WORLD);
293 
294  message(0, "MPSort total time: %g\n", end - start);
295  }
296  myfree(base);
297 }
void message(int where, const char *fmt,...)
Definition: endrun.c:175
#define mpsort_mpi_newarray(base, nmemb, out, outnmemb, elsize, radix, rsize, arg, comm)
Definition: mpsort.h:30
#define mymalloc(name, size)
Definition: mymalloc.h:15
#define myfree(x)
Definition: mymalloc.h:19
static uint64_t checksum_minid(struct BaseGroup *data, size_t localsize, MPI_Comm comm)
Definition: test_mpsort.c:239
int compar_bg(void *d1, void *d2)
Definition: test_mpsort.c:216
static void fof_radix_Group_TotalCountTaskDiffMinID(const void *a, void *radix, void *arg)
Definition: test_mpsort.c:208
static void check_sorted(void *data, int elsize, size_t localsize, int compar(void *d1, void *d2), MPI_Comm comm)
Definition: test_mpsort.c:58

References check_sorted(), checksum_minid(), compar_bg(), endrun(), fof_radix_Group_TotalCountTaskDiffMinID(), BaseGroup::Length, message(), BaseGroup::MinID, BaseGroup::MinIDTask, mpsort_mpi_newarray, myfree, mymalloc, NTask, BaseGroup::OriginalTask, and ThisTask.

Referenced by test_basegroup().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ do_mpsort_test()

static void do_mpsort_test ( int64_t  srcsize,
int  bits,
int  staggered,
int  gather 
)
static

Definition at line 138 of file test_mpsort.c.

139 {
140  int ThisTask;
141  int NTask;
142 
143  MPI_Comm_size(MPI_COMM_WORLD, &NTask);
144  MPI_Comm_rank(MPI_COMM_WORLD, &ThisTask);
145 
146  if(gather == 1)
148  if(gather == 0)
150 
151 // message(0, "NTask = %d\n", NTask);
152 // message(0, "src size = %ld\n", srcsize);
153 
154  if(staggered && (ThisTask % 2 == 0)) srcsize = 0;
155 
156  int64_t csize;
157 
158  MPI_Allreduce(&srcsize, &csize, 1, MPI_LONG, MPI_SUM, MPI_COMM_WORLD);
159 
160  int64_t destsize = csize * (ThisTask + 1) / NTask - csize * (ThisTask) / NTask;
161 
162  message(0, "dest size = %ld\n", destsize);
163 // message(0, "csize = %ld\n", csize);
164 
165  int64_t * src = mymalloc("src", srcsize * sizeof(int64_t));
166  int64_t * dest = mymalloc("dest", destsize * sizeof(int64_t));
167 
168  int seed = 9999 * ThisTask;
169  generate(src, srcsize, bits, seed);
170 
171  int64_t srcsum = checksum(src, srcsize, MPI_COMM_WORLD);
172 // if(ThisTask == 0)
173 // mpsort_setup_timers(512);
174  {
175  double start = MPI_Wtime();
176 
177  mpsort_setup_timers(512);
178  mpsort_mpi_newarray(src, srcsize,
179  dest, destsize,
180  sizeof(int64_t),
181  radix_int, sizeof(int64_t), NULL,
182  MPI_COMM_WORLD);
183 
184  MPI_Barrier(MPI_COMM_WORLD);
185  double end = MPI_Wtime();
186 
187  int64_t destsum = checksum(dest, destsize, MPI_COMM_WORLD);
188 
189  if(destsum != srcsum) {
190  endrun(5, "MPSort checksum is inconsistent.\n");
191  MPI_Abort(MPI_COMM_WORLD, -1);
192  }
193 
194  check_sorted(dest, sizeof(int64_t), destsize, compar_int, MPI_COMM_WORLD);
195 
196  message(0, "MPSort total time: %g\n", end - start);
197 // if(ThisTask == 0) {
198 // mpsort_mpi_report_last_run();
199 // mpsort_free_timers();
200 // }
201  }
202 
204  myfree(dest);
205  myfree(src);
206 }
void mpsort_mpi_unset_options(int options)
Definition: mpsort.c:1451
void mpsort_mpi_set_options(int options)
Definition: mpsort.c:1437
void mpsort_setup_timers(int ntimers)
Definition: mpsort.c:736
#define MPSORT_REQUIRE_GATHER_SORT
Definition: mpsort.h:6
#define MPSORT_DISABLE_GATHER_SORT
Definition: mpsort.h:5
static void radix_int(const void *ptr, void *radix, void *arg)
Definition: test_mpsort.c:27
static int64_t checksum(int64_t *data, size_t localsize, MPI_Comm comm)
Definition: test_mpsort.c:32
static void generate(int64_t *data, size_t localsize, int bits, int seed)
Definition: test_mpsort.c:44
int compar_int(void *d1, void *d2)
Definition: test_mpsort.c:125

References check_sorted(), checksum(), compar_int(), endrun(), generate(), message(), MPSORT_DISABLE_GATHER_SORT, mpsort_mpi_newarray, mpsort_mpi_set_options(), mpsort_mpi_unset_options(), MPSORT_REQUIRE_GATHER_SORT, mpsort_setup_timers(), myfree, mymalloc, NTask, radix_int(), and ThisTask.

Referenced by test_mpsort_bits(), test_mpsort_gather(), and test_mpsort_stagger().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ fof_radix_Group_TotalCountTaskDiffMinID()

static void fof_radix_Group_TotalCountTaskDiffMinID ( const void *  a,
void *  radix,
void *  arg 
)
static

Definition at line 208 of file test_mpsort.c.

208  {
209  uint64_t * u = (uint64_t *) radix;
210  struct BaseGroup * f = (struct BaseGroup *) a;
211  u[0] = labs(f->OriginalTask - f->MinIDTask);
212  u[1] = f->MinID;
213  u[2] = UINT64_MAX - (f->Length);
214 }

References BaseGroup::Length, BaseGroup::MinID, BaseGroup::MinIDTask, and BaseGroup::OriginalTask.

Referenced by do_long_radix_test().

Here is the caller graph for this function:

◆ generate()

static void generate ( int64_t *  data,
size_t  localsize,
int  bits,
int  seed 
)
static

Definition at line 44 of file test_mpsort.c.

45 {
46  /* only keep bits of precision. */
47  srandom(seed);
48 
49  size_t i;
50  unsigned shift = 64u - bits;
51  for(i = 0; i < localsize; i ++) {
52  uint64_t value = (int64_t) random() * (int64_t) random() * random() * random();
53  data[i] = (signed) ((value << shift));
54  }
55 }

Referenced by do_mpsort_test().

Here is the caller graph for this function:

◆ main()

int main ( void  )

Definition at line 337 of file test_mpsort.c.

338 {
339  const struct CMUnitTest tests[] = {
340  cmocka_unit_test(test_mpsort_bits),
341  cmocka_unit_test(test_mpsort_stagger),
342  cmocka_unit_test(test_basegroup),
343  cmocka_unit_test(test_mpsort_gather),
344  };
345  return cmocka_run_group_tests_mpi(tests, NULL, NULL);
346 }
static void test_basegroup(void **state)
Definition: test_mpsort.c:300
static void test_mpsort_gather(void **state)
Definition: test_mpsort.c:329
static void test_mpsort_stagger(void **state)
Definition: test_mpsort.c:320
static void test_mpsort_bits(void **state)
Definition: test_mpsort.c:308

References test_basegroup(), test_mpsort_bits(), test_mpsort_gather(), and test_mpsort_stagger().

Here is the call graph for this function:

◆ radix_int()

static void radix_int ( const void *  ptr,
void *  radix,
void *  arg 
)
static

Definition at line 27 of file test_mpsort.c.

27  {
28  *(uint64_t*)radix = *(const int64_t*) ptr + INT64_MIN;
29 }

Referenced by do_mpsort_test().

Here is the caller graph for this function:

◆ test_basegroup()

static void test_basegroup ( void **  state)
static

Definition at line 300 of file test_mpsort.c.

301 {
302  do_long_radix_test(50);
303  /* This is chosen because it fails in travis*/
305 }
static void do_long_radix_test(int srcsize)
Definition: test_mpsort.c:253

References do_long_radix_test().

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ test_mpsort_bits()

static void test_mpsort_bits ( void **  state)
static

Definition at line 308 of file test_mpsort.c.

309 {
310  message(0, "16 bits!\n");
311  /* With whatever gather we like*/
312  do_mpsort_test(2000, 16, 0, -1);
313  message(0, "32 bits!\n");
314  do_mpsort_test(2000, 32, 0, -1);
315  message(0, "64 bits!\n");
316  do_mpsort_test(2000, 64, 0, -1);
317 }
static void do_mpsort_test(int64_t srcsize, int bits, int staggered, int gather)
Definition: test_mpsort.c:138

References do_mpsort_test(), and message().

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ test_mpsort_gather()

static void test_mpsort_gather ( void **  state)
static

Definition at line 329 of file test_mpsort.c.

330 {
331  /* With forced gather*/
332  do_mpsort_test(2000, 32, 0, 1);
333  /* Without forced gather*/
334  do_mpsort_test(2000, 32, 0, 0);
335 }

References do_mpsort_test().

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ test_mpsort_stagger()

static void test_mpsort_stagger ( void **  state)
static

Definition at line 320 of file test_mpsort.c.

321 {
322  /* With stagger*/
323  do_mpsort_test(2000, 32, 1, -1);
324  /* Use a number that doesn't divide evenly so we get a different destsize*/
325  do_mpsort_test(1999, 32, 0, -1);
326 }

References do_mpsort_test().

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function: