KMR
testwfmap.c
1 /* testwfmap.c (2016-07-14) */
2 
3 /* Check simple workflow operations. Run this with (nprocs>=32+1). */
4 
5 #include <mpi.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <unistd.h>
9 #include <strings.h>
10 #include <fcntl.h>
11 #include <limits.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <sys/time.h>
15 #include <assert.h>
16 #ifdef _OPENMP
17 #include <omp.h>
18 #endif
19 
20 #include "kmr.h"
21 #include "kmrimpl.h"
22 
23 /* When MINIMINITEST=1, run tests in cases with very small processes
24  (with nprocs>=3 or nprocs>=5). It is for development. */
25 
26 #define MINIMINITEST (1)
27 
28 const int MINNPROCS = (32+1);
29 
30 /* Configuration of Processes (Case 0). */
31 
32 int lanes0vector[4][20] = {
33  {2,2, 0},
34  {4,4, 4,4, 0},
35  {2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,2,2, /*(remainings are spares)*/ 0},
36  {0}
37 };
38 
39 int *lanes0[4] = {
40  lanes0vector[0],
41  lanes0vector[1],
42  lanes0vector[2],
43  0
44 };
45 
46 /* Configuration of Processes (Case 1). A different way of describing
47  the same configuration as above. */
48 
49 char *lanes1[] = {
50  "0.0.0:2",
51  "0.0.1:2",
52  "0.0.2:2",
53  "0.0.3:2",
54  "0.1.0:2",
55  "0.1.1:2",
56  "0.1.2:2",
57  "0.1.3:2",
58  "1.0.0:2",
59  "1.0.1:2",
60  "1.0.2:2",
61  "1.0.3:2",
62  "1.1.0:2",
63  "1.1.1:2",
64  "1.1.2:2",
65  "1.1.3:2",
66  0};
67 
68 static int
69 iindex(int e, int *vector, int length)
70 {
71  for (int i = 0; i < length; i++) {
72  if (vector[i] == e) {
73  return i;
74  }
75  }
76  return -1;
77 }
78 
79 /* Runs degenerated test cases. CASE: TESTCASE=0 to 5: It just checks
80  the workflow control (not execute binaries). It needs nprocs=3 for
81  TESTCASE=0..3, and nprocs=5 for TESTCASE=4..5. CASE: TESTCASE=6: It
82  needs nprocs=3. */
83 
84 static void
85 minimini(int TESTCASE, int nprocs, int rank)
86 {
87  int masterrank = (nprocs - 1);
88  int root = 0;
89 
90  assert(0 <= TESTCASE && TESTCASE <= 9);
91 
92  int cc;
93 
94  MPI_Barrier(MPI_COMM_WORLD);
95  usleep(50 * 1000);
96  if (rank == 0) {
97  printf("MINI RUN (case %d)...\n", TESTCASE);
98  fflush(0);
99  }
100 
101  KMR *mr = kmr_create_context(MPI_COMM_WORLD, MPI_INFO_NULL, 0);
102  assert(mr != 0);
103  if (TESTCASE <= 5) {
104  /* Disable the spawning library. */
105  mr->swf_spawner_library = strdup("NONE.so");
106  }
107  mr->trace_map_spawn = 0;
108 
109  char *lanesdesc0[] = {
110  "0:2",
111  0
112  };
113  char *lanesdesc1[] = {
114  "0.0:2",
115  0
116  };
117  char *lanesdesc2[] = {
118  "0.0.0:2",
119  0
120  };
121  char *lanesdesc3[] = {
122  "0.0.0.0:2",
123  0
124  };
125  char *lanesdesc4[] = {
126  "0.0:2",
127  "0.1:2",
128  0
129  };
130  char *lanesdesc5[] = {
131  "0:1",
132  "1:1",
133  "2:1",
134  "3:1",
135  0
136  };
137  char *lanesdesc6[] = {
138  "0:2",
139  0
140  };
141  char **lanesdesclist[10] = {
142  lanesdesc0, lanesdesc1, lanesdesc2, lanesdesc3, lanesdesc4,
143  lanesdesc5, lanesdesc6, lanesdesc0, lanesdesc0, lanesdesc0
144  };
145 
146  char **lanesdesc = lanesdesclist[TESTCASE];
147 
148  if (rank == 0) {
149  printf("Lane description of tests:\n");
150  char **d;
151  d = lanesdesc;
152  while (*d != 0) {
153  printf("%s\n", *d);
154  d++;
155  }
156  fflush(0);
157  }
158 
159  MPI_Comm splitcomms[4];
160  cc = kmr_split_swf_lanes(mr, splitcomms, root, lanesdesc, 1);
161  assert(cc == MPI_SUCCESS);
162 
163  mr->swf_debug_master = 1;
164  cc = kmr_init_swf(mr, splitcomms, masterrank);
165  assert(cc == MPI_SUCCESS);
166 
167  if (rank == masterrank) {
168  printf("Test runs using the following lanes:\n");
169  fflush(0);
170  }
171  kmr_dump_swf_lanes(mr);
172 
173  mr->trace_map_spawn = 0;
174  kmr_set_swf_verbosity(mr, 2);
175  cc = kmr_detach_swf_workers(mr);
176  assert(cc == MPI_SUCCESS);
177 
178  /* ONLY THE MASTER RANK COMES HERE. */
179 
180  assert(rank == masterrank);
181 
182  if (1) {
183  usleep(50 * 1000);
184  printf("Minimini 10 works. Check the trace log...\n");
185  fflush(0);
186  usleep(50 * 1000);
187 
188  KMR_KVS *kvs00 = kmr_create_kvs(mr, KMR_KV_OPAQUE, KMR_KV_OPAQUE);
189  {
190  char kbuf[256];
191  char vbuf[256];
192  for (int i = 0; i < 10; i++) {
193 
194  /* Make key. */
195 
196  if (TESTCASE == 0) {
197  snprintf(kbuf, sizeof(kbuf), "0");
198  } else if (TESTCASE == 1) {
199  if (i % 3 == 0) {
200  snprintf(kbuf, sizeof(kbuf), "0");
201  } else {
202  snprintf(kbuf, sizeof(kbuf), "0.0");
203  }
204  } else if (TESTCASE == 2) {
205  if (i % 3 == 0) {
206  snprintf(kbuf, sizeof(kbuf), "0");
207  } else {
208  snprintf(kbuf, sizeof(kbuf), "0.0.0");
209  }
210  } else if (TESTCASE == 3) {
211  if (i % 3 == 0) {
212  snprintf(kbuf, sizeof(kbuf), "0");
213  } else {
214  snprintf(kbuf, sizeof(kbuf), "0.0.0.0");
215  }
216  } else if (TESTCASE == 4) {
217  if (i % 3 == 0) {
218  snprintf(kbuf, sizeof(kbuf), "0");
219  } else if (i % 2 == 0) {
220  snprintf(kbuf, sizeof(kbuf), "0.0");
221  } else {
222  snprintf(kbuf, sizeof(kbuf), "0.1");
223  }
224  } else if (TESTCASE == 5) {
225  snprintf(kbuf, sizeof(kbuf), "%d", (i % 4));
226  } else if (TESTCASE == 6) {
227  snprintf(kbuf, sizeof(kbuf), "0");
228  } else {
229  snprintf(kbuf, sizeof(kbuf), "0");
230  }
231 
232  /* Make value. */
233 
234  if (TESTCASE <= 4) {
235  snprintf(vbuf, sizeof(vbuf),
236  ("maxprocs=2 ./a.out work! index=%d lane=%s"
237  " blah blah blah"), i, kbuf);
238  } else if (TESTCASE == 5) {
239  snprintf(vbuf, sizeof(vbuf),
240  ("maxprocs=1 ./a.out work! index=%d lane=%s"
241  " blah blah blah"), i, kbuf);
242  } else if (TESTCASE == 6) {
243  snprintf(vbuf, sizeof(vbuf),
244  ("maxprocs=2 ./a.out work! index=%d lane=%s"
245  " blah blah blah"), i, kbuf);
246  } else {
247  snprintf(vbuf, sizeof(vbuf),
248  ("maxprocs=2 ./a.out work! index=%d lane=%s"
249  " blah blah blah"), i, kbuf);
250  }
251 
252  struct kmr_kv_box nkv = {
253  .klen = (int)(strlen(kbuf) + 1),
254  .vlen = (int)(strlen(vbuf) + 1),
255  .k.p = kbuf,
256  .v.p = vbuf};
257  kmr_add_kv(kvs00, nkv);
258  }
259  }
260  kmr_add_kv_done(kvs00);
261  KMR_KVS *kvs01 = kmr_create_kvs(mr, KMR_KV_OPAQUE, KMR_KV_OPAQUE);
262  struct kmr_spawn_option opt = {.separator_space = 1};
263  mr->trace_map_spawn = 1;
264  mr->swf_record_history = 1;
265  kmr_map_swf(kvs00, kvs01, (void *)0, opt, 0);
266  kmr_free_kvs(kvs00);
267  kmr_free_kvs(kvs01);
268 
269  if (0) {
271  }
272 
273  printf("Minimini 10 works done.\n");
274  fflush(0);
275  }
276 
277  MPI_Barrier(MPI_COMM_SELF);
278 
279  cc = kmr_stop_swf_workers(mr);
280  assert(cc == MPI_SUCCESS);
281  cc = kmr_free_context(mr);
282  assert(cc == MPI_SUCCESS);
283 
284  kmr_fin();
285  MPI_Finalize();
286 }
287 
288 static void
289 simple0(int nprocs, int rank)
290 {
291  int masterrank = (nprocs - 1);
292  int root = 0;
293 
294  int cc;
295 
296  MPI_Barrier(MPI_COMM_WORLD);
297  usleep(50 * 1000);
298  if (rank == 0) {
299  printf("CHECK WORKFLOW-MAPPER...\n");
300  printf("Run this test with 33 or more processes.\n");
301  fflush(0);
302  }
303 
304  if (nprocs < MINNPROCS) {
305  if (rank == 0) {
306  printf("THIS TEST NEEDS 32+1 OR MORE PROCESSES.\n");
307  fflush(0);
308  }
309  usleep(50 * 1000);
310  MPI_Finalize();
311  exit(1);
312  }
313 
314  KMR *mr = kmr_create_context(MPI_COMM_WORLD, MPI_INFO_NULL, 0);
315  assert(mr != 0);
316  mr->trace_map_spawn = 0;
317 
318  MPI_Comm splitcomms[4];
319 
320  if (0) {
321  cc = kmr_split_swf_lanes_a(mr, splitcomms, root, lanes0, 1);
322  assert(cc == MPI_SUCCESS);
323  } else {
324  cc = kmr_split_swf_lanes(mr, splitcomms, root, lanes1, 1);
325  assert(cc == MPI_SUCCESS);
326  }
327 
328  sleep(3);
329 
330  mr->swf_debug_master = 1;
331  cc = kmr_init_swf(mr, splitcomms, masterrank);
332  assert(cc == MPI_SUCCESS);
333 
334  if (rank == masterrank) {
335  printf("Test runs using the following lanes:\n");
336  fflush(0);
337  }
338  kmr_dump_swf_lanes(mr);
339 
340  sleep(3);
341 
342  printf("[%05d] Detaching workers...\n", rank);
343  fflush(0);
344 
345  mr->trace_map_spawn = 0;
346  cc = kmr_detach_swf_workers(mr);
347  assert(cc == MPI_SUCCESS);
348 
349  sleep(3);
350 
351  /* ONLY THE MASTER RANK COMES HERE. */
352 
353  assert(rank == masterrank);
354 
355  /* This part is to check trace using the eyes. */
356 
357  if (1) {
358  usleep(50 * 1000);
359  printf("Simple 100 works. Check the trace log...\n");
360  fflush(0);
361  usleep(50 * 1000);
362 
363  int level0 = 2;
364  int level1 = 2;
365  int level2 = 4;
366  int n_lanes = (level0 * level1 * level2);
367 
368  KMR_KVS *kvs00 = kmr_create_kvs(mr, KMR_KV_OPAQUE, KMR_KV_OPAQUE);
369  {
370  char kbuf[256];
371  char vbuf[256];
372  for (int i = 0; i < 100; i++) {
373  int lane = (rand() % n_lanes);
374  int index1 = ((lane / level2) % level1);
375  int index0 = (lane / (level1 * level2));
376  snprintf(kbuf, sizeof(kbuf),
377  "%d.%d.*", index0, index1);
378  snprintf(vbuf, sizeof(vbuf),
379  ("maxprocs=2 ./a.out work! index=%d lane=%s"
380  " blah blah blah"), i, kbuf);
381  struct kmr_kv_box nkv = {
382  .klen = (int)(strlen(kbuf) + 1),
383  .vlen = (int)(strlen(vbuf) + 1),
384  .k.p = kbuf,
385  .v.p = vbuf};
386  kmr_add_kv(kvs00, nkv);
387  }
388  }
389  kmr_add_kv_done(kvs00);
390  KMR_KVS *kvs01 = kmr_create_kvs(mr, KMR_KV_OPAQUE, KMR_KV_OPAQUE);
391  struct kmr_spawn_option opt = {.separator_space = 1};
392  mr->trace_map_spawn = 1;
393  mr->swf_record_history = 1;
394  kmr_map_swf(kvs00, kvs01, (void *)0, opt, 0);
395  kmr_free_kvs(kvs00);
396  kmr_free_kvs(kvs01);
397 
398  if (0) {
400  }
401 
402  int count = 100;
403  int history[count];
404  kmr_dump_swf_order_history(mr, history, (size_t)count);
405 
406  if (0) {
407  usleep(50 * 1000);
408  printf("History (finish ordering of work-items):\n");
409  for (int i = 0; i < count; i++) {
410  if (i == 0) {
411  printf("%d", history[i]);
412  } else if ((i % 15) == 0) {
413  printf(",\n");
414  printf("%d", history[i]);
415  } else {
416  printf(",%d", history[i]);
417  }
418  }
419  printf("\n");
420  fflush(0);
421  }
422 
423  printf("Simple 100 works done.\n");
424  fflush(0);
425  }
426 
427  /* This part checks the ordering contraint by assertions. */
428 
429  if (0) {
430  usleep(50 * 1000);
431  printf("Simple 400 works...\n");
432  fflush(0);
433  usleep(50 * 1000);
434 
435  /* Let S as SETSIZE=10, G as GROUPS=4, L as ITERATION=10.
436  (GROUPS is fixed by the lane configuration). Each (S)th
437  element barriers elements in the same group. That is, the
438  barrier is the (G*S*i+S-1)th element, and (G*S*i'+j)th
439  elements finish before the barrier and (G*S*i''+j)th
440  elements start after the barrier, where 0<=j<S-1, 0<=i<L,
441  i'<i, i''>i. */
442 
443  int SETSIZE = 10;
444  int ITERATION = 10;
445  int GROUPS = 4;
446  assert(GROUPS == 4);
447  KMR_KVS *kvs00 = kmr_create_kvs(mr, KMR_KV_OPAQUE, KMR_KV_OPAQUE);
448  {
449  char kbuf[256];
450  char vbuf[256];
451  /* A set of works for 4 groups, for loop repeated 10 times. */
452  for (int iteration = 0; iteration < ITERATION; iteration++) {
453  for (int group = 0; group < 4; group++) {
454  int a = (group / 2);
455  int b = (group % 2);
456  /* (SETSIZE-1) works in (a.b.*). */
457  for (int i = 0; i < (SETSIZE - 1); i++) {
458  snprintf(kbuf, sizeof(kbuf), "%d.%d.*", a, b);
459  snprintf(vbuf, sizeof(vbuf),
460  "maxprocs=2 ./a.out simple0 blah blah");
461  struct kmr_kv_box nkv = {
462  .klen = (int)(strlen(kbuf) + 1),
463  .vlen = (int)(strlen(vbuf) + 1),
464  .k.p = kbuf,
465  .v.p = vbuf};
466  kmr_add_kv(kvs00, nkv);
467  }
468  /* 1 work in (a.b) which barriers previous set. */
469  snprintf(kbuf, sizeof(kbuf), "%d.%d", a, b);
470  snprintf(vbuf, sizeof(vbuf),
471  ("maxprocs=8 ./a.out simple0"
472  " iteration=%d blah blah"),
473  iteration);
474  struct kmr_kv_box nkv = {
475  .klen = (int)(strlen(kbuf) + 1),
476  .vlen = (int)(strlen(vbuf) + 1),
477  .k.p = kbuf,
478  .v.p = vbuf};
479  kmr_add_kv(kvs00, nkv);
480  }
481  }
482  }
483  kmr_add_kv_done(kvs00);
484  KMR_KVS *kvs01 = kmr_create_kvs(mr, KMR_KV_OPAQUE, KMR_KV_OPAQUE);
485  struct kmr_spawn_option opt = {.separator_space = 1};
486  mr->trace_map_spawn = 0;
487  mr->swf_record_history = 1;
488  kmr_map_swf(kvs00, kvs01, (void *)0, opt, 0);
489  kmr_free_kvs(kvs00);
490  kmr_free_kvs(kvs01);
491 
492  if (0) {
494  }
495 
496  int count = (4 * SETSIZE * 10);
497  int history[count];
498  kmr_dump_swf_order_history(mr, history, (size_t)count);
499 
500  if (0) {
501  usleep(50 * 1000);
502  printf("History (finish ordering of work-items):\n");
503  for (int i = 0; i < count; i++) {
504  if (i == 0) {
505  printf("%d", history[i]);
506  } else if ((i % 15) == 0) {
507  printf(",\n");
508  printf("%d", history[i]);
509  } else {
510  printf(",%d", history[i]);
511  }
512  }
513  printf("\n");
514  fflush(0);
515  }
516 
517  /* Check workflow ordering constraint. */
518 
519  if (1) {
520  printf("Checking ordering constraint...\n");
521  fflush(0);
522  for (int group = 0; group < 4; group++) {
523  for (int i = 0; i < ITERATION; i++) {
524  int barrier = (4*SETSIZE*i+SETSIZE-1);
525  int pos0 = iindex(barrier, history, count);
526  assert(pos0 != -1);
527  for (int i1 = 0; i1 < i; i1++) {
528  for (int j = 0; j < (SETSIZE - 1); j++) {
529  int prea = (4*SETSIZE*i1+j);
530  int pos1 = iindex(prea, history, count);
531  assert(pos1 != -1);
532  assert(pos1 < pos0);
533  }
534  }
535  for (int i2 = (i + 1); i2 < ITERATION; i2++) {
536  for (int j = 0; j < (SETSIZE - 1); j++) {
537  int post = (4*SETSIZE*i2+j);
538  int pos2 = iindex(post, history, count);
539  assert(pos2 != -1);
540  assert(pos0 < pos2);
541  }
542  }
543  }
544  }
545  }
546 
547  printf("Simple 400 works done.\n");
548  fflush(0);
549  }
550 
551  MPI_Barrier(MPI_COMM_SELF);
552 
553  cc = kmr_stop_swf_workers(mr);
554  assert(cc == MPI_SUCCESS);
555  cc = kmr_free_context(mr);
556  assert(cc == MPI_SUCCESS);
557 
558  kmr_fin();
559  MPI_Finalize();
560 }
561 
562 int
563 main(int argc, char *argv[])
564 {
565 #define digitp(X) ('0' <= (X) && (X) <= '9')
566 
567 #if 0
568  /*AHO*/ printf("AHOAHO argc=%d\n", argc); fflush(0);
569  /*AHO*/ printf("AHOAHO argv[0]=%s\n", argv[0]); fflush(0);
570  /*AHO*/ printf("AHOAHO argv[1]=%s\n", argv[1]); fflush(0);
571  /*AHO*/ printf("AHOAHO argv[1]=%s strcmp(argv[1], work!)=%d\n",
572  argv[1], (strcmp(argv[1], "work!") == 0));
573  fflush(0);
574  sleep(3);
575 #endif
576 
577  if (argc == 1 || (argc == 2 && argv[1][1] == 0 && digitp(argv[1][0]))) {
578 
579  /* MAIN RUN (Argument: None or a single digit). */
580 
581  int testcase = ((argc == 2) ? (argv[1][0] - '0') : 0);
582  assert(0 <= testcase && testcase <= 9);
583 
584  int nprocs, rank, thlv;
585  MPI_Init_thread(&argc, &argv, MPI_THREAD_SERIALIZED, &thlv);
586  MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
587  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
588 
589  if (rank == 0) {
590 #ifdef NDEBUG
591  _Bool assertion = 0;
592 #else
593  _Bool assertion = 1;
594 #endif
595  if (!assertion) {
596  kmr_error(0, "Assertion disabled; recompile this test");
597  return 1;
598  }
599  }
600 
601  kmr_init();
602 
603  if (!MINIMINITEST) {
604  if (rank == 0) {
605  if (nprocs < MINNPROCS) {
606  fprintf(stderr, "RUN THIS WITH 33 PROCS OR MORE.\n");
607  fflush(0);
608  abort();
609  return 1;
610  }
611  }
612  simple0(nprocs, rank);
613  } else {
614  minimini(testcase, nprocs, rank);
615  }
616 
617  usleep(50 * 1000);
618  {printf("OK\n");}
619  fflush(0);
620 
621  return 0;
622  } else if (argc >= 2 && strcmp(argv[1], "work!") == 0) {
623 
624  /* RUN INVOKED BY WORKERS (Argument: "work!"). */
625 
626  {printf("A work started\n"); fflush(0);}
627 
628  int thlv;
629  MPI_Init_thread(&argc, &argv, MPI_THREAD_SERIALIZED, &thlv);
630  int nprocs, rank;
631  MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
632  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
633 
634  {printf("A work with nprocs=%d rank=%d\n", nprocs, rank); fflush(0);}
635 
636  MPI_Finalize();
637  exit(0);
638  return 0;
639  } else {
640  fprintf(stderr, "RUN WITH BAD ARGUMENTS.\n");
641  fflush(0);
642  abort();
643  return 1;
644  }
645 }
Key-Value Stream (abstract).
Definition: kmr.h:632
Utilities Private Part (do not include from applications).
int kmr_map_swf(KMR_KVS *kvi, KMR_KVS *kvo, void *arg, struct kmr_spawn_option opt, kmr_mapfn_t mapfn)
Maps with a simple workflow.
Definition: kmrwfmap.c:2112
int kmr_add_kv(KMR_KVS *kvs, const struct kmr_kv_box kv)
Adds a key-value pair.
Definition: kmrbase.c:809
int kmr_init_swf(KMR *mr, MPI_Comm lanecomms[KMR_LANE_LEVELS], int master)
Initializes the lanes of simple workflow.
Definition: kmrwfmap.c:528
#define kmr_create_kvs(MR, KF, VF)
Makes a new key-value stream (of type KMR_KVS) with the specified field datatypes.
Definition: kmr.h:71
void kmr_set_swf_verbosity(KMR *mr, int level)
Sets the verbosity of the spawn-library.
Definition: kmrwfmap.c:505
int kmr_add_kv_done(KMR_KVS *kvs)
Marks finished adding key-value pairs.
Definition: kmrbase.c:939
KMR Context.
Definition: kmr.h:247
int kmr_free_kvs(KMR_KVS *kvs)
Releases a key-value stream (type KMR_KVS).
Definition: kmrbase.c:679
int kmr_split_swf_lanes_a(KMR *mr, MPI_Comm splitcomms[KMR_LANE_LEVELS], int root, int *description[], _Bool dump)
Splits a communicator in a KMR context to ones to be used for kmr_init_swf().
Definition: kmrwfmap.c:930
Handy Copy of a Key-Value Field.
Definition: kmr.h:401
Options to Mapping by Spawns.
Definition: kmr.h:708
int kmr_stop_swf_workers(KMR *mr)
Finishes the workers of workflow.
Definition: kmrwfmap.c:731
int kmr_fin(void)
Clears the environment.
Definition: kmrbase.c:124
void kmr_dump_swf_history(KMR *mr)
Prints the history of kmr_map_swf(), which is the start ordering the work-items.
Definition: kmrwfmap.c:2874
#define kmr_init()
Sets up the environment.
Definition: kmr.h:794
int kmr_detach_swf_workers(KMR *mr)
Disengages the workers from main processing and puts them in the service loop for spawning...
Definition: kmrwfmap.c:659
int kmr_split_swf_lanes(KMR *mr, MPI_Comm splitcomms[KMR_LANE_LEVELS], int root, char *description[], _Bool dump)
Splits a communicator in a KMR context to ones to be used for kmr_init_swf().
Definition: kmrwfmap.c:1067
void kmr_dump_swf_lanes(KMR *mr)
Dumps lanes created by kmr_init_swf().
Definition: kmrwfmap.c:2054
int kmr_free_context(KMR *mr)
Releases a context created with kmr_create_context().
Definition: kmrbase.c:367
KMR Interface.
void kmr_dump_swf_order_history(KMR *mr, int *history, size_t length)
Returns a list of start ordering of the work-items.
Definition: kmrwfmap.c:2904
KMR * kmr_create_context(const MPI_Comm comm, const MPI_Info conf, const char *name)
Makes a new KMR context (a context has type KMR).
Definition: kmrbase.c:168