source: CIVL/examples/omp/simple/dijkstra_openmp.c.s

main
Last change on this file was ea777aa, checked in by Alex Wilton <awilton@…>, 3 years ago

Moved examples, include, build_default.properties, common.xml, and README out from dev.civl.com into the root of the repo.

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@5704 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 12.7 KB
Line 
1# include <stdlib.h>
2# include <stdio.h>
3# include <time.h>
4# include <omp.h>
5
6# define NV 6
7
8int main ( int argc, char **argv );
9int *dijkstra_distance ( int ohd[NV][NV] );
10void find_nearest ( int s, int e, int mind[NV], int connected[NV], int *d,
11 int *v );
12void init ( int ohd[NV][NV] );
13void timestamp ( void );
14void update_mind ( int s, int e, int mv, int connected[NV], int ohd[NV][NV],
15 int mind[NV] );
16
17/******************************************************************************/
18
19int main ( int argc, char **argv )
20
21/******************************************************************************/
22/*
23 Purpose:
24
25 MAIN runs an example of Dijkstra's minimum distance algorithm.
26
27 Discussion:
28
29 Given the distance matrix that defines a graph, we seek a list
30 of the minimum distances between node 0 and all other nodes.
31
32 This program sets up a small example problem and solves it.
33
34 The correct minimum distances are:
35
36 0 35 15 45 49 41
37
38 Licensing:
39
40 This code is distributed under the GNU LGPL license.
41
42 Modified:
43
44 01 July 2010
45
46 Author:
47
48 Original C version by Norm Matloff, CS Dept, UC Davis.
49 This C version by John Burkardt.
50*/
51{
52 int i;
53 int i4_huge = 2147483647;
54 int j;
55 int *mind;
56 int ohd[NV][NV];
57
58 timestamp ( );
59 fprintf ( stdout, "\n" );
60 fprintf ( stdout, "DIJKSTRA_OPENMP\n" );
61 fprintf ( stdout, " C version\n" );
62 fprintf ( stdout, " Use Dijkstra's algorithm to determine the minimum\n" );
63 fprintf ( stdout, " distance from node 0 to each node in a graph,\n" );
64 fprintf ( stdout, " given the distances between each pair of nodes.\n" );
65 fprintf ( stdout, "\n" );
66 fprintf ( stdout, " Although a very small example is considered, we\n" );
67 fprintf ( stdout, " demonstrate the use of OpenMP directives for\n" );
68 fprintf ( stdout, " parallel execution.\n" );
69/*
70 Initialize the problem data.
71*/
72 init ( ohd );
73/*
74 Print the distance matrix.
75*/
76 fprintf ( stdout, "\n" );
77 fprintf ( stdout, " Distance matrix:\n" );
78 fprintf ( stdout, "\n" );
79 for ( i = 0; i < NV; i++ )
80 {
81 for ( j = 0; j < NV; j++ )
82 {
83 if ( ohd[i][j] == i4_huge )
84 {
85 fprintf ( stdout, " Inf" );
86 }
87 else
88 {
89 fprintf ( stdout, " %3d", ohd[i][j] );
90 }
91 }
92 fprintf ( stdout, "\n" );
93 }
94/*
95 Carry out the algorithm.
96*/
97 mind = dijkstra_distance ( ohd );
98/*
99 Print the results.
100*/
101 fprintf ( stdout, "\n" );
102 fprintf ( stdout, " Minimum distances from node 0:\n");
103 fprintf ( stdout, "\n" );
104 for ( i = 0; i < NV; i++ )
105 {
106 fprintf ( stdout, " %2d %2d\n", i, mind[i] );
107 }
108/*
109 Free memory.
110*/
111 free ( mind );
112/*
113 Terminate.
114*/
115 fprintf ( stdout, "\n" );
116 fprintf ( stdout, "DIJKSTRA_OPENMP\n" );
117 fprintf ( stdout, " Normal end of execution.\n" );
118
119 fprintf ( stdout, "\n" );
120 timestamp ( );
121
122 return 0;
123}
124/******************************************************************************/
125
126int *dijkstra_distance ( int ohd[NV][NV] )
127
128/******************************************************************************/
129/*
130 Purpose:
131
132 DIJKSTRA_DISTANCE uses Dijkstra's minimum distance algorithm.
133
134 Discussion:
135
136 We essentially build a tree. We start with only node 0 connected
137 to the tree, and this is indicated by setting CONNECTED[0] = 1.
138
139 We initialize MIND[I] to the one step distance from node 0 to node I.
140
141 Now we search among the unconnected nodes for the node MV whose minimum
142 distance is smallest, and connect it to the tree. For each remaining
143 unconnected node I, we check to see whether the distance from 0 to MV
144 to I is less than that recorded in MIND[I], and if so, we can reduce
145 the distance.
146
147 After NV-1 steps, we have connected all the nodes to 0, and computed
148 the correct minimum distances.
149
150 Licensing:
151
152 This code is distributed under the GNU LGPL license.
153
154 Modified:
155
156 02 July 2010
157
158 Author:
159
160 Original C version by Norm Matloff, CS Dept, UC Davis.
161 This C version by John Burkardt.
162
163 Parameters:
164
165 Input, int OHD[NV][NV], the distance of the direct link between
166 nodes I and J.
167
168 Output, int DIJKSTRA_DISTANCE[NV], the minimum distance from
169 node 0 to each node.
170*/
171{
172 int *connected;
173 int i;
174 int i4_huge = 2147483647;
175 int md;
176 int *mind;
177 int mv;
178 int my_first;
179 int my_id;
180 int my_last;
181 int my_md;
182 int my_mv;
183 int my_step;
184 int nth;
185/*
186 Start out with only node 0 connected to the tree.
187*/
188 connected = ( int * ) malloc ( NV * sizeof ( int ) );
189
190 connected[0] = 1;
191 for ( i = 1; i < NV; i++ )
192 {
193 connected[i] = 0;
194 }
195/*
196 Initial estimate of minimum distance is the 1-step distance.
197*/
198 mind = ( int * ) malloc ( NV * sizeof ( int ) );
199
200 for ( i = 0; i < NV; i++ )
201 {
202 mind[i] = ohd[0][i];
203 }
204/*
205 Begin the parallel region.
206*/
207 # pragma omp parallel private ( my_first, my_id, my_last, my_md, my_mv, my_step ) \
208 shared ( connected, md, mind, mv, nth, ohd )
209 {
210 my_id = omp_get_thread_num ( );
211 nth = omp_get_num_threads ( );
212 my_first = ( my_id * NV ) / nth;
213 my_last = ( ( my_id + 1 ) * NV ) / nth - 1;
214/*
215 The SINGLE directive means that the block is to be executed by only
216 one thread, and that thread will be whichever one gets here first.
217*/
218 # pragma omp single
219 {
220 printf ( "\n" );
221 printf ( " P%d: Parallel region begins with %d threads\n", my_id, nth );
222 printf ( "\n" );
223 }
224 fprintf ( stdout, " P%d: First=%d Last=%d\n", my_id, my_first, my_last );
225
226 for ( my_step = 1; my_step < NV; my_step++ )
227 {
228/*
229 Before we compare the results of each thread, set the shared variable
230 MD to a big value. Only one thread needs to do this.
231*/
232 # pragma omp single
233 {
234 md = i4_huge;
235 mv = -1;
236 }
237/*
238 Each thread finds the nearest unconnected node in its part of the graph.
239 Some threads might have no unconnected nodes left.
240*/
241 find_nearest ( my_first, my_last, mind, connected, &my_md, &my_mv );
242/*
243 In order to determine the minimum of all the MY_MD's, we must insist
244 that only one thread at a time execute this block!
245*/
246 # pragma omp critical
247 {
248 if ( my_md < md )
249 {
250 md = my_md;
251 mv = my_mv;
252 }
253 }
254/*
255 This barrier means that ALL threads have executed the critical
256 block, and therefore MD and MV have the correct value. Only then
257 can we proceed.
258*/
259 # pragma omp barrier
260/*
261 If MV is -1, then NO thread found an unconnected node, so we're done early.
262 OpenMP does not like to BREAK out of a parallel region, so we'll just have
263 to let the iteration run to the end, while we avoid doing any more updates.
264
265 Otherwise, we connect the nearest node.
266*/
267 # pragma omp single
268 {
269 if ( mv != - 1 )
270 {
271 connected[mv] = 1;
272 printf ( " P%d: Connecting node %d.\n", my_id, mv );
273 }
274 }
275/*
276 Again, we don't want any thread to proceed until the value of
277 CONNECTED is updated.
278*/
279 # pragma omp barrier
280/*
281 Now each thread should update its portion of the MIND vector,
282 by checking to see whether the trip from 0 to MV plus the step
283 from MV to a node is closer than the current record.
284*/
285 if ( mv != -1 )
286 {
287 update_mind ( my_first, my_last, mv, connected, ohd, mind );
288 }
289/*
290 Before starting the next step of the iteration, we need all threads
291 to complete the updating, so we set a BARRIER here.
292*/
293 #pragma omp barrier
294 }
295/*
296 Once all the nodes have been connected, we can exit.
297*/
298 # pragma omp single
299 {
300 printf ( "\n" );
301 printf ( " P%d: Exiting parallel region.\n", my_id );
302 }
303 }
304
305 free ( connected );
306
307 return mind;
308}
309/******************************************************************************/
310
311void find_nearest ( int s, int e, int mind[NV], int connected[NV], int *d,
312 int *v )
313
314/******************************************************************************/
315/*
316 Purpose:
317
318 FIND_NEAREST finds the nearest unconnected node.
319
320 Licensing:
321
322 This code is distributed under the GNU LGPL license.
323
324 Modified:
325
326 02 July 2010
327
328 Author:
329
330 Original C version by Norm Matloff, CS Dept, UC Davis.
331 This C version by John Burkardt.
332
333 Parameters:
334
335 Input, int S, E, the first and last nodes that are to be checked.
336
337 Input, int MIND[NV], the currently computed minimum distance from
338 node 0 to each node.
339
340 Input, int CONNECTED[NV], is 1 for each connected node, whose
341 minimum distance to node 0 has been determined.
342
343 Output, int *D, the distance from node 0 to the nearest unconnected
344 node in the range S to E.
345
346 Output, int *V, the index of the nearest unconnected node in the range
347 S to E.
348*/
349{
350 int i;
351 int i4_huge = 2147483647;
352
353 *d = i4_huge;
354 *v = -1;
355
356 for ( i = s; i <= e; i++ )
357 {
358 if ( !connected[i] && ( mind[i] < *d ) )
359 {
360 *d = mind[i];
361 *v = i;
362 }
363 }
364 return;
365}
366/******************************************************************************/
367
368void init ( int ohd[NV][NV] )
369
370/******************************************************************************/
371/*
372 Purpose:
373
374 INIT initializes the problem data.
375
376 Discussion:
377
378 The graph uses 6 nodes, and has the following diagram and
379 distance matrix:
380
381 N0--15--N2-100--N3 0 40 15 Inf Inf Inf
382 \ | / 40 0 20 10 25 6
383 \ | / 15 20 0 100 Inf Inf
384 40 20 10 Inf 10 100 0 Inf Inf
385 \ | / Inf 25 Inf Inf 0 8
386 \ | / Inf 6 Inf Inf 8 0
387 N1
388 / \
389 / \
390 6 25
391 / \
392 / \
393 N5----8-----N4
394
395 Licensing:
396
397 This code is distributed under the GNU LGPL license.
398
399 Modified:
400
401 02 July 2010
402
403 Author:
404
405 Original C version by Norm Matloff, CS Dept, UC Davis.
406 This C version by John Burkardt.
407
408 Parameters:
409
410 Output, int OHD[NV][NV], the distance of the direct link between
411 nodes I and J.
412*/
413{
414 int i;
415 int i4_huge = 2147483647;
416 int j;
417
418 for ( i = 0; i < NV; i++ )
419 {
420 for ( j = 0; j < NV; j++ )
421 {
422 if ( i == j )
423 {
424 ohd[i][i] = 0;
425 }
426 else
427 {
428 ohd[i][j] = i4_huge;
429 }
430 }
431 }
432 ohd[0][1] = ohd[1][0] = 40;
433 ohd[0][2] = ohd[2][0] = 15;
434 ohd[1][2] = ohd[2][1] = 20;
435 ohd[1][3] = ohd[3][1] = 10;
436 ohd[1][4] = ohd[4][1] = 25;
437 ohd[2][3] = ohd[3][2] = 100;
438 ohd[1][5] = ohd[5][1] = 6;
439 ohd[4][5] = ohd[5][4] = 8;
440
441 return;
442}
443/******************************************************************************/
444
445void timestamp ( void )
446
447/******************************************************************************/
448/*
449 Purpose:
450
451 TIMESTAMP prints the current YMDHMS date as a time stamp.
452
453 Example:
454
455 31 May 2001 09:45:54 AM
456
457 Licensing:
458
459 This code is distributed under the GNU LGPL license.
460
461 Modified:
462
463 24 September 2003
464
465 Author:
466
467 John Burkardt
468
469 Parameters:
470
471 None
472*/
473{
474# define TIME_SIZE 40
475
476 static char time_buffer[TIME_SIZE];
477 const struct tm *tm;
478 size_t len;
479 time_t now;
480
481 now = time ( NULL );
482 tm = localtime ( &now );
483
484 len = strftime ( time_buffer, TIME_SIZE, "%d %B %Y %I:%M:%S %p", tm );
485
486 printf ( "%s\n", time_buffer );
487
488 return;
489# undef TIME_SIZE
490}
491/******************************************************************************/
492
493void update_mind ( int s, int e, int mv, int connected[NV], int ohd[NV][NV],
494 int mind[NV] )
495
496/******************************************************************************/
497/*
498 Purpose:
499
500 UPDATE_MIND updates the minimum distance vector.
501
502 Discussion:
503
504 We've just determined the minimum distance to node MV.
505
506 For each unconnected node I in the range S to E,
507 check whether the route from node 0 to MV to I is shorter
508 than the currently known minimum distance.
509
510 Licensing:
511
512 This code is distributed under the GNU LGPL license.
513
514 Modified:
515
516 02 July 2010
517
518 Author:
519
520 Original C version by Norm Matloff, CS Dept, UC Davis.
521 This C version by John Burkardt.
522
523 Parameters:
524
525 Input, int S, E, the first and last nodes that are to be checked.
526
527 Input, int MV, the node whose minimum distance to node 0
528 has just been determined.
529
530 Input, int CONNECTED[NV], is 1 for each connected node, whose
531 minimum distance to node 0 has been determined.
532
533 Input, int OHD[NV][NV], the distance of the direct link between
534 nodes I and J.
535
536 Input/output, int MIND[NV], the currently computed minimum distances
537 from node 0 to each node. On output, the values for nodes S through
538 E have been updated.
539*/
540{
541 int i;
542 int i4_huge = 2147483647;
543
544 for ( i = s; i <= e; i++ )
545 {
546 if ( !connected[i] )
547 {
548 if ( ohd[mv][i] < i4_huge )
549 {
550 if ( mind[mv] + ohd[mv][i] < mind[i] )
551 {
552 mind[i] = mind[mv] + ohd[mv][i];
553 }
554 }
555 }
556 }
557 return;
558}
Note: See TracBrowser for help on using the repository browser.