Skip to content

Commit 541da03

Browse files
authored
Create floyd_warshall_openmp.c
1 parent fac3c38 commit 541da03

File tree

1 file changed

+308
-0
lines changed

1 file changed

+308
-0
lines changed

floyd_warshall_openmp.c

Lines changed: 308 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
1+
/*
2+
* This file contains code that is the parallelized version of
3+
* Floyd Warshall: All-Pair-Shortest-Path algorithm, written in C using
4+
* OpenMP. Floyd Warshall algorithm basically finds all pair shortest
5+
* paths in a weighted graph and use dynamic programming technique to
6+
* solve the problem.
7+
*
8+
* Compiling: via 1) GNU
9+
* 2) Oracle Solaris
10+
*
11+
* 1) gcc -o floyd_warshal_omp -fopenmp floyd_warshal_omp.c
12+
*
13+
* - or -
14+
*
15+
* 2) cc -o floyd_warshal_omp -xopenmp floyd_warshal_omp.c
16+
*
17+
* Running:
18+
*
19+
* ./floyd_warshal_omp [DATA_FILE_NAME] [NUMBER_OF_THREADS]
20+
*
21+
* Example: ./floyd_warshal_omp test_data_1000.dat 4
22+
*
23+
*
24+
* File: floyd_warshal_omp.c Author: Inteasar Haider
25+
* Date: January 01, 2017 Version: V1.0
26+
*
27+
*/
28+
29+
#include <omp.h>
30+
#include <string.h>
31+
#include <stdio.h>
32+
#include <stdlib.h>
33+
#include <limits.h>
34+
#include <sys/time.h>
35+
36+
/* Print matrix after initialization and calculating shortest path
37+
* 1 = Print matrix
38+
* 0 = Do not print matrix
39+
*
40+
*/
41+
#define PRINT_MATRIX 0
42+
#define MIN_NODES 4 /* Minimun nodes in graph */
43+
#define DATA_FOLDER "../test_data/"
44+
45+
static void calculate_all_pair_shortest_path (void);
46+
static void print_distance_adjacency_matrix (void);
47+
static void calculate_execution_time (struct timeval time_start,
48+
struct timeval time_end);
49+
static int read_data_from_file (char data_file_name[]);
50+
51+
/* adjacency matrix to store distance between nodes of directed graph */
52+
int **nodes_distance;
53+
int num_nodes;
54+
55+
int main (int argc, char *argv[])
56+
{
57+
int num_threads; /* threads to start upon execution */
58+
struct timeval time_start, time_end; /* to hold start & end time */
59+
60+
/* File name and number of threads to spawn will be passed via
61+
* command line as CLI parameter
62+
* First param (argv[1]) will be file name
63+
* Second param (argv[2]) will be number of threads to spawn
64+
*/
65+
if( argc == 3 ) {
66+
read_data_from_file (argv[1]);
67+
num_threads = atoi(argv[2]);
68+
} else {
69+
printf ("==> Error: Data file name (e.g: test_data_10.dat) as 1st "
70+
"and number of threads as 2nd parameter is not passed "
71+
"from command line\n\n");
72+
return EXIT_FAILURE;
73+
}
74+
75+
printf ("==> Spawning %d threads to calculate shortest paths between"
76+
" %d nodes..\n\n", num_threads, num_nodes);
77+
78+
print_distance_adjacency_matrix ();
79+
80+
gettimeofday (&time_start, NULL);
81+
82+
/* entering into the parallel region */
83+
#pragma omp parallel num_threads(num_threads) shared(nodes_distance)
84+
calculate_all_pair_shortest_path ();
85+
/* exiting from the parallel region */
86+
87+
gettimeofday (&time_end, NULL);
88+
89+
calculate_execution_time (time_start, time_end);
90+
91+
print_distance_adjacency_matrix ();
92+
93+
free(nodes_distance);
94+
return EXIT_SUCCESS;
95+
}
96+
97+
/* This routine will be executed in parallel region and it's
98+
* responsibility is to calculate shortest path and update shorter
99+
* path distance in nodes_distance matrix.
100+
*
101+
* num_nodes will be evenly distributed among all threads and each
102+
* thread will perform calculation simultaneously on given dataset to
103+
* find the shortest distance between two nodes i and j via one
104+
* intermediate node i.e K at a time and update, if found, shortest
105+
* path in the nodes_distance matrix.
106+
*
107+
* Once an iteration of an intermediate node i.e 'K' is done, all the
108+
* threads will wait for others before starting the next iteration of
109+
* intermediate node and that iteration will run (num_nodes-1) times.
110+
*
111+
* input parameters: none
112+
* output parameters: nodes_distance will have all shortest paths
113+
* return value: none
114+
*
115+
*/
116+
void calculate_all_pair_shortest_path(void)
117+
{
118+
int possible_short_dist; /* to hold distance between i and j via k */
119+
120+
for (int k = 0; k < num_nodes; ++k)
121+
{
122+
/*
123+
* Wait for all threads to complete the iteration before we do
124+
* shortest path calculations on the adjacency matrix for next
125+
* intermediate node
126+
*
127+
*/
128+
# pragma omp barrier
129+
130+
# pragma omp for
131+
for (int i = 0; i < num_nodes; ++i)
132+
{
133+
for (int j = 0; j < num_nodes; ++j)
134+
{
135+
/* if both nodes (i & j) are not same and path between node_i
136+
* and Node_j via node_k exists (i.e. anything except 0)
137+
*
138+
*/
139+
if ( (nodes_distance[i][k] * nodes_distance[k][j] != 0)
140+
&& (i != j) )
141+
{
142+
possible_short_dist = nodes_distance[i][k] +
143+
nodes_distance[k][j];
144+
145+
/* If path exists between i and j and that path distance
146+
* is already lesser than newly calculated distance
147+
* (via Node_k) do not update anything and continue with
148+
* other possibilities
149+
*
150+
*/
151+
if ( (nodes_distance[i][j] <= possible_short_dist) &&
152+
(nodes_distance[i][j] != 0) )
153+
{
154+
continue;
155+
}
156+
157+
/* Replace the current distance with new shortest distance */
158+
nodes_distance[i][j] = possible_short_dist;
159+
}
160+
}
161+
}
162+
}
163+
}
164+
165+
/* Responsibility of this routine is to calculate final execution time
166+
* of the program
167+
*
168+
* input parameters: Two params of timeval struct
169+
* a) time_start: time when program entered in to
170+
* parallel regions and threads were spawned
171+
* b) time_end: when all threads completed working
172+
*
173+
* output parameters: Printing time spent on the console
174+
* return value: none
175+
*
176+
*/
177+
void calculate_execution_time (struct timeval time_start,
178+
struct timeval time_end)
179+
{
180+
long long execution_time = 1000000LL
181+
* (time_end.tv_sec - time_start.tv_sec)
182+
+ (time_end.tv_usec - time_start.tv_usec);
183+
184+
double time_spent = (double) execution_time / 1000000;
185+
printf ("==> Finished calculating shortest path in %f seconds.\n\n",
186+
time_spent );
187+
}
188+
189+
/* Responsibility of this routine is to print two dimensional matrix
190+
* that contains the distance between the nodes of given graph
191+
*
192+
* input parameters: none
193+
* output: distance matrix printed on the console
194+
* return value: none
195+
* side effects: could crash console if a huge matrix is being
196+
* printed
197+
*
198+
*/
199+
void print_distance_adjacency_matrix (void)
200+
{
201+
if(PRINT_MATRIX==1)
202+
{
203+
int i, j;
204+
printf(" ");
205+
206+
for (i = 0; i < num_nodes; ++i)
207+
{
208+
printf("%4c", 'A' + i);
209+
}
210+
211+
printf("\n");
212+
213+
for (i = 0; i < num_nodes; ++i)
214+
{
215+
printf("%4c", 'A' + i);
216+
for (j = 0; j < num_nodes; ++j)
217+
{
218+
printf("%4d", nodes_distance[i][j]);
219+
}
220+
printf("\n");
221+
}
222+
223+
printf("\n");
224+
}
225+
}
226+
227+
/* Responsibility of this routine is to populate the distance matrix
228+
* with the test data being read from file
229+
*
230+
* input parameters: File name passed as a CLI Parameter
231+
* output: distance matrix with test data
232+
* return value: 1 if unable to populate data
233+
* 0 if data is populated successfully
234+
* side effects: could crash program if test data file is
235+
* missing or contain in un-appropriate data
236+
*
237+
*/
238+
int read_data_from_file (char data_file_name[])
239+
{
240+
FILE *data_file;
241+
int temp = 0; /* hold data read from file temporarily */
242+
int mem_size; /* memory to allocate for adjacency matrix */
243+
244+
char final_path[40];
245+
246+
strcpy( final_path, DATA_FOLDER ); /* copy data folder path */
247+
strcat( final_path, data_file_name ); /* create file path */
248+
249+
data_file = fopen (final_path, "r");
250+
251+
if(data_file == NULL)
252+
{
253+
printf ("==> Cannot proceed, unable to find data file ..\n\n");
254+
exit(EXIT_FAILURE);
255+
}
256+
257+
/* The first line will be the number of vertices */
258+
fscanf (data_file, "%d", &num_nodes);
259+
260+
if(num_nodes <= MIN_NODES) /* graph should not be empty */
261+
{
262+
printf ("==> Cannot proceed, invalid graph size given ..\n\n");
263+
exit(EXIT_FAILURE);
264+
}
265+
266+
/* Calculating memory needed for adjacency matrix */
267+
mem_size = (num_nodes * sizeof(int*)) +
268+
(num_nodes * num_nodes * sizeof(int));
269+
270+
/* Dynamically allocating memory for the adjacency matrix */
271+
nodes_distance = malloc (mem_size);
272+
273+
/* Set the row indexes as pointers to the columns */
274+
for (int i = 0; i < num_nodes; ++i)
275+
{
276+
nodes_distance[i] = (int*)(nodes_distance + num_nodes + 1) +
277+
(i * num_nodes);
278+
}
279+
280+
printf("%d num_nodes being read from data file... \n", num_nodes);
281+
282+
for (int i = 0; i < num_nodes; i++)
283+
{
284+
for (int j = 0; j < num_nodes; j++)
285+
{
286+
if (fscanf (data_file, "%d", &temp) == EOF)
287+
{
288+
break;
289+
}
290+
else
291+
{
292+
if (i == j)
293+
{
294+
/* distance between same node should be set zero */
295+
nodes_distance[i][j] = 0;
296+
}
297+
else
298+
{
299+
/* reading data from file */
300+
nodes_distance[i][j]= temp;
301+
}
302+
}
303+
}
304+
}
305+
fclose (data_file);
306+
307+
return EXIT_SUCCESS;
308+
}

0 commit comments

Comments
 (0)