COMBINATORIAL_BLAS 1.6
 
Loading...
Searching...
No Matches
labelprop.cpp
Go to the documentation of this file.
1/*
2//@HEADER
3// *****************************************************************************
4//
5// HPCGraph: Graph Computation on High Performance Computing Systems
6// Copyright (2016) Sandia Corporation
7//
8// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9// the U.S. Government retains certain rights in this software.
10//
11// Redistribution and use in source and binary forms, with or without
12// modification, are permitted provided that the following conditions are
13// met:
14//
15// 1. Redistributions of source code must retain the above copyright
16// notice, this list of conditions and the following disclaimer.
17//
18// 2. Redistributions in binary form must reproduce the above copyright
19// notice, this list of conditions and the following disclaimer in the
20// documentation and/or other materials provided with the distribution.
21//
22// 3. Neither the name of the Corporation nor the names of the
23// contributors may be used to endorse or promote products derived from
24// this software without specific prior written permission.
25//
26// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37//
38// Questions? Contact George M. Slota (gmslota@sandia.gov)
39// Siva Rajamanickam (srajama@sandia.gov)
40// Kamesh Madduri (madduri@cse.psu.edu)
41//
42// *****************************************************************************
43//@HEADER
44*/
45
46
47#include <mpi.h>
48#include <omp.h>
49#include <stdio.h>
50#include <stdlib.h>
51#include <stdint.h>
52#include <fstream>
53#include <unordered_map>
54#include <vector>
55
56#include "dist_graph.h"
57#include "comms.h"
58#include "util.h"
59#include "labelprop.h"
60
61#define LABEL_NOT_ASSIGNED 18446744073709551615
62
63extern int procid, nprocs;
64extern bool verbose, debug, verify;
65
66
68 uint64_t*& labels, uint32_t num_iter)
69{
70 if (debug) { printf("Task %d run_labelprop() start\n", procid); }
71 double elt = 0.0;
72 if (verbose) {
73 MPI_Barrier(MPI_COMM_WORLD);
74 elt = omp_get_wtime();
75 }
76
77 uint64_t* labels_next = (uint64_t*)malloc(g->n_total*sizeof(uint64_t));
78
79 for (int32_t i = 0; i < nprocs; ++i)
80 comm->sendcounts_temp[i] = 0;
81
82#pragma omp parallel default(shared)
83{
86 //std::unordered_map<uint64_t, uint64_t> map;
87 //std::vector<uint64_t> max_labels;
88 fast_map map;
89 init_map(&map, (g->max_out_degree + g->max_in_degree)*2);
90
91#pragma omp for
92 for (uint64_t i = 0; i < g->n_local; ++i)
93 labels[i] = g->local_unmap[i];
94#pragma omp for
95 for (uint64_t i = 0; i < g->n_local; ++i)
96 labels_next[i] = g->local_unmap[i];
97#pragma omp for
98 for (uint64_t i = 0; i < g->n_ghost; ++i)
99 labels[i+g->n_local] = g->ghost_unmap[i];
100#pragma omp for
101 for (uint64_t i = 0; i < g->n_ghost; ++i)
102 labels_next[i+g->n_local] = g->ghost_unmap[i];
103
104
105#pragma omp for schedule(guided) nowait
106 for (uint64_t i = 0; i < g->n_local; ++i)
107 update_sendcounts_thread(g, &tc, i);
108
109 for (int32_t i = 0; i < nprocs; ++i)
110 {
111#pragma omp atomic
112 comm->sendcounts_temp[i] += tc.sendcounts_thread[i];
113
114 tc.sendcounts_thread[i] = 0;
115 }
116#pragma omp barrier
117
118#pragma omp single
119{
122}
123
124#pragma omp for schedule(guided) nowait
125 for (uint64_t i = 0; i < g->n_local; ++i)
126 update_vid_data_queues(g, &tc, comm, i, labels[i]);
127
128 empty_vid_data(&tc, comm);
129#pragma omp barrier
130
131#pragma omp single
132{
133 exchange_verts(comm);
134 exchange_data(comm);
135}
136
137#pragma omp for
138 for (uint64_t i = 0; i < comm->total_recv; ++i)
139 {
140 uint64_t index = get_value(&g->map, comm->recvbuf_vert[i]);
141 labels[index] = comm->recvbuf_data[i];
142 comm->recvbuf_vert[i] = index;
143 }
144
145#pragma omp for
146 for (uint64_t i = 0; i < comm->total_send; ++i)
147 {
148 uint64_t index = get_value(&g->map, comm->sendbuf_vert[i]);
149 comm->sendbuf_vert[i] = index;
150 }
151
152 for (uint32_t iter = 0; iter < num_iter; ++iter)
153 {
154 if (debug && tc.tid == 0) {
155 printf("Task %d Iter %u run_labelprop()\n", procid, iter);
156 }
157
158#pragma omp for schedule(guided) nowait
159 for (uint64_t i = 0; i < g->n_local; ++i)
160 {
161 uint64_t vert_index = i;
162 empty_map(&map);
163 //map.clear();
164
165 // uint64_t max_label = labels[vert_index];
166 // uint64_t max_label_count = 0;
167
168 uint64_t out_degree = out_degree(g, vert_index);
169 uint64_t* outs = out_vertices(g, vert_index);
170 for (uint64_t j = 0; j < out_degree; ++j)
171 {
172 uint64_t out_index = outs[j];
173 uint64_t label_out = labels[out_index];
174 // if (map.count(label_out) == 0)
175 // map[label_out] = 1;
176 // else
177 // map[label_out] = map[label_out] + 1;
178
179 // if (map[label_out] > max_label_count)
180 // {
181 // max_label = label_out;
182 // max_labels.clear();
183 // max_labels.push_back(label_out);
184 // }
185 // else if (map[label_out] == max_label_count)
186 // {
187 // max_labels.push_back(label_out);
188 // max_label = max_labels[rand() % max_labels.size()];
189 // }
190 uint64_t val = get_value(&map, label_out);
191 if (val == NULL_KEY)
192 set_value_uq(&map, label_out, 1);
193 else
194 set_value(&map, label_out, val+1);
195
196 }
197 uint64_t in_degree = in_degree(g, vert_index);
198 uint64_t* ins = in_vertices(g, vert_index);
199 for (uint64_t j = 0; j < in_degree; ++j)
200 {
201 uint64_t in_index = ins[j];
202 uint64_t label_in = labels[in_index];
203 // if (map.count(label_in) == 0)
204 // map[label_in] = 1;
205 // else
206 // map[label_in] = map[label_in] + 1;
207
208 // if (map[label_in] > max_label_count)
209 // {
210 // max_label = label_in;
211 // max_labels.clear();
212 // max_labels.push_back(label_in);
213 // }
214 // else if (map[label_in] == max_label_count)
215 // {
216 // max_labels.push_back(label_in);
217 // max_label = max_labels[rand() % max_labels.size()];
218 // }
219 uint64_t val = get_value(&map, label_in);
220 if (val == NULL_KEY)
221 set_value_uq(&map, label_in, 1);
222 else
223 set_value(&map, label_in, val+1);
224 }
225 // labels_next[vert_index] = max_label;
226
227 labels_next[vert_index] = get_max_key(&map);
228 if (labels_next[vert_index] == NULL_KEY)
229 labels_next[vert_index] = labels[vert_index];
230 }
231
232#pragma omp for
233 for (uint64_t i = 0; i < comm->total_send; ++i)
234 comm->sendbuf_data[i] = labels_next[comm->sendbuf_vert[i]];
235
236#pragma omp single
237{
238 exchange_data(comm);
239}
240
241#pragma omp for
242 for (uint64_t i = 0; i < comm->total_recv; ++i)
243 labels_next[comm->recvbuf_vert[i]] = comm->recvbuf_data[i];
244
245#pragma omp single
246{
247 uint64_t* temp = labels;
248 labels = labels_next;
249 labels_next = temp;
250}
251 } // end for loop
252
254} // end parallel
255
257 free(labels_next);
258
259 if (verbose) {
260 elt = omp_get_wtime() - elt;
261 printf("Task %d, run_labelprop() time %9.6f (s)\n", procid, elt);
262 }
263 if (debug) { printf("Task %d run_labelprop() success\n", procid); }
264
265 return 0;
266}
267
268
269
270int labelprop_output(dist_graph_t* g, uint64_t* labels, char* output_file)
271{
272 if (debug) printf("Task %d labels to %s\n", procid, output_file);
273
274 uint64_t* global_labels = (uint64_t*)malloc(g->n*sizeof(uint64_t));
275
276#pragma omp parallel for
277 for (uint64_t i = 0; i < g->n; ++i)
278 global_labels[i] = LABEL_NOT_ASSIGNED;
279
280#pragma omp parallel for
281 for (uint64_t i = 0; i < g->n_local; ++i)
282 global_labels[g->local_unmap[i]] = labels[i];
283
284
285 if (procid == 0)
286 MPI_Reduce(MPI_IN_PLACE, global_labels, (int32_t)g->n,
287 MPI_UINT64_T, MPI_MIN, 0, MPI_COMM_WORLD);
288 else
289 MPI_Reduce(global_labels, global_labels, (int32_t)g->n,
290 MPI_UINT64_T, MPI_MIN, 0, MPI_COMM_WORLD);
291
292 if (procid == 0)
293 {
294 if (debug)
295 for (uint64_t i = 0; i < g->n; ++i)
296 if (global_labels[i] == LABEL_NOT_ASSIGNED)
297 {
298 printf("Labels error: %lu not assigned\n", i);
299 global_labels[i] = 0;
300 }
301
302 std::ofstream outfile;
303 outfile.open(output_file);
304
305 for (uint64_t i = 0; i < g->n; ++i)
306 outfile << global_labels[i] << std::endl;
307
308 outfile.close();
309 }
310
311 free(global_labels);
312
313 if (debug) printf("Task %d done writing labels\n", procid);
314
315 return 0;
316}
317
318int labelprop_verify(dist_graph_t* g, uint64_t* labels, uint64_t num_to_output)
319{
320 if (debug) { printf("Task %d labelprop_verify() start\n", procid); }
321
322 uint64_t* global_labels = (uint64_t*)malloc(g->n*sizeof(uint64_t));
323 uint64_t* label_counts = (uint64_t*)malloc(g->n*sizeof(uint64_t));
324
325#pragma omp parallel for
326 for (uint64_t i = 0; i < g->n; ++i)
327 global_labels[i] = LABEL_NOT_ASSIGNED;
328
329#pragma omp parallel for
330 for (uint64_t i = 0; i < g->n_local; ++i)
331 global_labels[g->local_unmap[i]] = labels[i];
332
333 if (procid == 0)
334 MPI_Reduce(MPI_IN_PLACE, global_labels, (int32_t)g->n,
335 MPI_UINT64_T, MPI_MIN, 0, MPI_COMM_WORLD);
336 else
337 MPI_Reduce(global_labels, global_labels, (int32_t)g->n,
338 MPI_UINT64_T, MPI_MIN, 0, MPI_COMM_WORLD);
339
340 if (procid == 0)
341 {
342#pragma omp parallel for
343 for (uint64_t i = 0; i < g->n; ++i)
344 label_counts[i] = 0;
345
346 for (uint64_t i = 0; i < g->n; ++i)
347 ++label_counts[global_labels[i]];
348
349 quicksort_dec(label_counts, global_labels, (int64_t)0, (int64_t)g->n-1);
350
351 for (uint64_t i = 0; i < num_to_output; ++i)
352 printf("LP VERIFY %lu: label: %lu, size: %lu\n", i, global_labels[i], label_counts[i]);
353 }
354
355 free(global_labels);
356 free(label_counts);
357
358 if (debug) { printf("Task %d labelprop_verify() success\n", procid); }
359
360 return 0;
361}
362
364 uint32_t num_iter, char* output_file)
365{
366 if (debug) { printf("Task %d labelprop_dist() start\n", procid); }
367
368 MPI_Barrier(MPI_COMM_WORLD);
369 double elt = omp_get_wtime();
370
371 uint64_t* labels = (uint64_t*)malloc(g->n_total*sizeof(uint64_t));
372 run_labelprop(g, comm, labels, num_iter);
373
374 MPI_Barrier(MPI_COMM_WORLD);
375 elt = omp_get_wtime() - elt;
376 if (procid == 0) printf("LabelProp time %9.6f (s)\n", elt);
377
378 if (output) {
379 labelprop_output(g, labels, output_file);
380 }
381
382 if (verify) {
383 labelprop_verify(g, labels, 100);
384 }
385
386 free(labels);
387
388 if (debug) printf("Task %d labelprop_dist() success\n", procid);
389 return 0;
390}
391
void init_thread_comm(thread_comm_t *tc)
Definition comms.cpp:169
void init_recvbuf_vid_data(mpi_data_t *comm)
Definition comms.cpp:278
bool output
Definition comms.cpp:56
void init_sendbuf_vid_data(mpi_data_t *comm)
Definition comms.cpp:251
void clear_allbuf_vid_data(mpi_data_t *comm)
Definition comms.cpp:370
void clear_thread_comm(thread_comm_t *tc)
Definition comms.cpp:199
void empty_vid_data(thread_comm_t *tc, mpi_data_t *comm)
Definition comms.h:792
void exchange_verts(dist_graph_t *g, mpi_data_t *comm, queue_data_t *q)
Definition comms.h:184
void exchange_data(mpi_data_t *comm)
Definition comms.h:428
void update_vid_data_queues(dist_graph_t *g, thread_comm_t *tc, mpi_data_t *comm, uint64_t vert_index, uint64_t data)
Definition comms.h:628
void update_sendcounts_thread(dist_graph_t *g, thread_comm_t *tc, uint64_t vert_index)
Definition comms.h:563
long int64_t
Definition compat.h:21
#define in_degree(g, n)
Definition dist_graph.h:55
#define out_vertices(g, n)
Definition dist_graph.h:56
#define out_degree(g, n)
Definition dist_graph.h:54
#define in_vertices(g, n)
Definition dist_graph.h:57
void empty_map(fast_map *map)
Definition fast_map.cpp:131
void init_map(fast_map *map)
Definition fast_map.cpp:63
#define NULL_KEY
Definition fast_map.h:58
uint64_t get_max_key(fast_map *map)
Definition fast_map.h:143
void set_value(fast_map *map, uint64_t key, uint64_t value)
Definition fast_map.h:90
uint64_t get_value(fast_map *map, uint64_t key)
Definition fast_map.h:132
void set_value_uq(fast_map *map, uint64_t key, uint64_t value)
Definition fast_map.h:109
int procid
Definition main.cpp:55
bool debug
Definition labelprop.cpp:64
#define LABEL_NOT_ASSIGNED
Definition labelprop.cpp:61
int labelprop_output(dist_graph_t *g, uint64_t *labels, char *output_file)
int labelprop_dist(dist_graph_t *g, mpi_data_t *comm, uint32_t num_iter, char *output_file)
bool verify
Definition labelprop.cpp:64
int labelprop_verify(dist_graph_t *g, uint64_t *labels, uint64_t num_to_output)
bool verbose
Definition main.cpp:56
int nprocs
Definition labelprop.cpp:63
int run_labelprop(dist_graph_t *g, mpi_data_t *comm, uint64_t *&labels, uint32_t num_iter)
Definition labelprop.cpp:67
unsigned int uint32_t
Definition stdint.h:80
signed int int32_t
Definition stdint.h:77
unsigned __int64 uint64_t
Definition stdint.h:90
uint64_t n_total
Definition dist_graph.h:69
uint64_t max_out_degree
Definition dist_graph.h:72
uint64_t * local_unmap
Definition dist_graph.h:80
uint64_t * ghost_unmap
Definition dist_graph.h:81
uint64_t n_local
Definition dist_graph.h:66
uint64_t n_ghost
Definition dist_graph.h:68
uint64_t max_in_degree
Definition dist_graph.h:73
uint64_t n
Definition dist_graph.h:61
fast_map map
Definition dist_graph.h:83
uint64_t * sendbuf_data
Definition comms.h:79
uint64_t * sendcounts_temp
Definition comms.h:73
uint64_t total_send
Definition comms.h:86
uint64_t * recvbuf_data
Definition comms.h:82
uint64_t * sendbuf_vert
Definition comms.h:78
uint64_t total_recv
Definition comms.h:85
uint64_t * recvbuf_vert
Definition comms.h:81
int32_t tid
Definition comms.h:109
uint64_t * sendcounts_thread
Definition comms.h:111
void quicksort_dec(uint64_t *arr1, uint64_t *arr2, int64_t left, int64_t right)
Definition util.cpp:76