KMR
wordcount.c
1 /* Word Count (2014-02-04) */
2 
3 /* It ranks the words by their occurrence count in the "LICENSE" file.
4  Copy the file in the current directory and run it. */
5 
6 #include <mpi.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include "kmr.h"
11 
12 #define ISALPHA(X) (('a' <= X && X <= 'z') || ('A' <= X && X <= 'Z'))
13 
14 static int
15 read_words_from_a_file(const struct kmr_kv_box kv0,
16  const KMR_KVS *kvi, KMR_KVS *kvo, void *p, const long i)
17 {
18  char b[25];
19  assert(kvi == 0 && kv0.klen == 0 && kv0.vlen == 0 && kvo != 0);
20  FILE *f = fopen("LICENSE", "r");
21  if (f == 0) {
22  perror("Cannot open a file \"LICENSE\"; fopen(LICENSE)");
23  MPI_Abort(MPI_COMM_WORLD, 1);
24  return 0;
25  }
26  int j = 0;
27  for (;;) {
28  assert((size_t)j <= (sizeof(b) - 1));
29  int cc = getc(f);
30  if ((cc == EOF || !ISALPHA(cc) || (j == (sizeof(b) - 1))) && j != 0) {
31  b[j] = 0;
32  struct kmr_kv_box kv = {
33  .klen = (j + 1), .k.p = b,
34  .vlen = sizeof(long), .v.i = 1};
35  kmr_add_kv(kvo, kv);
36  j = 0;
37  }
38  if (cc == EOF) {
39  break;
40  }
41  if (ISALPHA(cc)) {
42  b[j] = (char)cc;
43  j++;
44  }
45  }
46  fclose(f);
47  return MPI_SUCCESS;
48 }
49 
50 static int
51 print_top_five(const struct kmr_kv_box kv0,
52  const KMR_KVS *kvi, KMR_KVS *kvo, void *p, const long i)
53 {
54  int rank = kvi->c.mr->rank;
55  if (rank == 0 && i < 5) {
56  printf("#%s=%d\n", kv0.v.p, (int)(0 - kv0.k.i));
57  fflush(0);
58  }
59  return MPI_SUCCESS;
60 }
61 
62 static int
63 sum_counts_for_a_word(const struct kmr_kv_box kv[], const long n,
64  const KMR_KVS *kvs, KMR_KVS *kvo, void *p)
65 {
66  long c = 0;
67  for (long i = 0; i < n; i++) {
68  c -= kv[i].v.i;
69  }
70  struct kmr_kv_box nkv = {
71  .klen = kv[0].klen,
72  .k.p = kv[0].k.p,
73  .vlen = sizeof(long),
74  .v.i = c};
75  kmr_add_kv(kvo, nkv);
76  return MPI_SUCCESS;
77 }
78 
79 int
80 main(int argc, char **argv)
81 {
82  int nprocs, rank, thlv;
83  MPI_Init_thread(&argc, &argv, MPI_THREAD_SERIALIZED, &thlv);
84  MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
85  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
86  kmr_init();
87  KMR *mr = kmr_create_context(MPI_COMM_WORLD, MPI_INFO_NULL, 0);
88 
89  MPI_Barrier(MPI_COMM_WORLD);
90  if (rank == 0) {printf("Ranking words...\n");}
91 
92  KMR_KVS *kvs0 = kmr_create_kvs(mr, KMR_KV_OPAQUE, KMR_KV_INTEGER);
93  kmr_map_once(kvs0, 0, kmr_noopt, 0, read_words_from_a_file);
94 
95  KMR_KVS *kvs1 = kmr_create_kvs(mr, KMR_KV_OPAQUE, KMR_KV_INTEGER);
96  kmr_shuffle(kvs0, kvs1, kmr_noopt);
97 
98  KMR_KVS *kvs2 = kmr_create_kvs(mr, KMR_KV_OPAQUE, KMR_KV_INTEGER);
99  kmr_reduce(kvs1, kvs2, 0, kmr_noopt, sum_counts_for_a_word);
100 
101  KMR_KVS *kvs3 = kmr_create_kvs(mr, KMR_KV_INTEGER, KMR_KV_OPAQUE);
102  kmr_reverse(kvs2, kvs3, kmr_noopt);
103 
104  KMR_KVS *kvs4 = kmr_create_kvs(mr, KMR_KV_INTEGER, KMR_KV_OPAQUE);
105  kmr_sort(kvs3, kvs4, kmr_noopt);
106 
107  kmr_map(kvs4, 0, 0, kmr_noopt, print_top_five);
108 
109  kmr_free_context(mr);
110  kmr_fin();
111  MPI_Finalize();
112  return 0;
113 }
Key-Value Stream (abstract).
Definition: kmr.h:587
#define kmr_reduce(KVI, KVO, ARG, OPT, R)
Reduces key-value pairs.
Definition: kmr.h:88
int kmr_add_kv(KMR_KVS *kvs, const struct kmr_kv_box kv)
Adds a key-value pair.
Definition: kmrbase.c:751
int kmr_map_once(KMR_KVS *kvo, void *arg, struct kmr_option opt, _Bool rank_zero_only, kmr_mapfn_t m)
Maps once.
Definition: kmrbase.c:1402
#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
int kmr_shuffle(KMR_KVS *kvi, KMR_KVS *kvo, struct kmr_option opt)
Shuffles key-value pairs to the appropriate destination ranks.
Definition: kmrbase.c:2036
KMR Context.
Definition: kmr.h:222
#define kmr_map(KVI, KVO, ARG, OPT, M)
Maps simply.
Definition: kmr.h:82
Handy Copy of a Key-Value Field.
Definition: kmr.h:358
int kmr_fin(void)
Clears the environment.
Definition: kmrbase.c:124
#define kmr_init()
Sets up the environment.
Definition: kmr.h:747
int kmr_sort(KMR_KVS *kvi, KMR_KVS *kvo, struct kmr_option opt)
Sorts a key-value stream globally.
Definition: kmrmoreops.c:575
int kmr_free_context(KMR *mr)
Releases a context created with kmr_create_context().
Definition: kmrbase.c:326
KMR Interface.
int kmr_reverse(KMR_KVS *kvi, KMR_KVS *kvo, struct kmr_option opt)
Makes a new pair by swapping the key and the value in each pair.
Definition: kmrmoreops.c:159
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:147