diff --git a/makefile b/makefile new file mode 100644 index 0000000000000000000000000000000000000000..49cd8448f9e4c1f02685d8737a4bd5b9458c6493 --- /dev/null +++ b/makefile @@ -0,0 +1,13 @@ +.SILENT: $ + +CC = gcc +FILE= omp_dijkstra + +# make compile +compile: $ + echo "compiling" + gcc -g -Wall -o ${FILE} ${FILE}.c -fopenmp + +# make run N={node_size} T={thread_count} +run: ./${FILE} + ./${FILE} ${N} ${T}\ diff --git a/src/graph.txt b/src/graph.txt new file mode 100644 index 0000000000000000000000000000000000000000..610053095bca563ae124305a177644c700e7ea87 --- /dev/null +++ b/src/graph.txt @@ -0,0 +1,5 @@ +0 19 70 14 21 +49 0 1 59 86 +41 37 0 73 6 +59 61 40 0 48 +93 56 25 92 0 diff --git a/src/omp_dijkstra.c b/src/omp_dijkstra.c new file mode 100644 index 0000000000000000000000000000000000000000..33648d7f0dca9e922d7cd175d9259bd030ce8aab --- /dev/null +++ b/src/omp_dijkstra.c @@ -0,0 +1,210 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <limits.h> +#include <time.h> +#include <omp.h> + +/********************************/ +/* GRAPH SIZES */ +/********************************/ +#define SIZE_1 100 +#define SIZE_2 500 +#define SIZE_3 1000 +#define SIZE_4 3000 + +#define V 3000 +int graph[V][V]; +int result[V][V]; + +// Graph attributes +clock_t begin, end; +int processorCount; + +/********************************/ +/* GRAPH CONTROLLERS */ +/********************************/ + +// Creates a new matrix +void generateGraph (int graph[V][V], int size) { + // Randomize matrix file + srand(13517131); + int i, j; + + for (i = 0; i < size; i++) + { + for (j = 0; j < size; j++) + { + if (i == j) { + graph[i][j] = 0; + } + else { + graph[i][j] = rand() % 100; + } + } + } +} + +// Print matrix +void printGraph(int graph[V][V], int size) { + int i, j; + for (i = 0; i < size; i++){ + for (j = 0; j < size; j++){ + printf("%d", graph[i][j]); + if (j != (size - 1)){ + printf(" "); + } + } + if(i != (size - 1)) { + printf("\n"); + } + } +} + +// Write to file +void writeToFile(int result[V][V], int size) { + FILE *fp; + fp = fopen("result.txt", "w"); + + for (int i = 0; i < size; i++) { + for (int j = 0; j < (size - 1); j++) { + fprintf(fp, "%d\t", result[i][j]); + } + fprintf(fp, "%d\n", result[i][size - 1]); + printf("Printed line: %d out of %d\n", i, size); + } +} + +void writeGraphToFile(int graph[V][V], int size) { + FILE *fp; + fp = fopen("graph.txt", "w"); + + for (int i = 0; i < size; i++) { + for (int j = 0; j < (size - 1); j++) { + fprintf(fp, "%d\t", graph[i][j]); + } + fprintf(fp, "%d\n", graph[i][size - 1]); + printf("Printed line: %d out of %d\n", i, size); + } +} + +/********************************/ +/* DIJKSTRA ALGORITHM */ +/********************************/ +// A utility function to find the vertex with minimum distance value, from +// the set of vertices not yet included in shortest path tree +int minDistance(int dist[], bool sptSet[], int size) +{ + // Initialize min value + int min = INT_MAX, min_index; + + for (int v = 0; v < size; v++) + if (sptSet[v] == false && dist[v] <= min) + min = dist[v], min_index = v; + + return min_index; +} + +// A utility function to print the constructed distance array +void printSolution(int dist[], int size, int src) +{ + printf("\nDijkstra for source %d\n", src); + printf("Vertex \t\t Distance from Source\n"); + for (int i = 0; i < size; i++) + printf("%d \t\t %d\n", i, dist[i]); +} + +// Function that implements Dijkstra's single source shortest path algorithm +// for a graph represented using adjacency matrix representation +// Courtesy of <geeksforgeeks.com> +void dijkstra(int graph[V][V], int src, int size, int dist[V]) { + bool sptSet[V]; + + for (int i = 0; i < size; i++) + dist[i] = INT_MAX, sptSet[i] = false; + + dist[src] = 0; + + for (int count = 0; count < size - 1; count++) { + int u = minDistance(dist, sptSet, size); + sptSet[u] = true; + + for (int v = 0; v < size; v++) + if (!sptSet[v] && graph[u][v] && dist[u] != INT_MAX + && dist[u] + graph[u][v] < dist[v]) + dist[v] = dist[u] + graph[u][v]; + } +} + +/********************************/ +/* PARALEL & SERIAL DIJKSTRA */ +/********************************/ +void serialDijkstra(int size) { + int i; + for (i = 0; i < size; i++) { + dijkstra(graph, i, size, result[i]); + printf("Set for node: %d out of %d\n", i, size); + } +} + +void paralelDijkstra(int size) { + int i,j; + int myRank = omp_get_thread_num(); + int thread_count = omp_get_num_threads(); + + printf("myRank = %d, thread_count = %d\n", myRank, thread_count); + printf("size = %d\n", size); + + for (i = myRank; i < size; i += thread_count) { + printf("test = %d\n", i); + dijkstra(graph, i, size, result[i]); + if (i == 0) { + for (j = 0; j < size; j++) { + printf("%d\n", result[i][j]); + } + } + printf("Set by thread %d for node: %d out of %d", myRank, i, size); + } +} + +/********************************/ +/* MAIN */ +/********************************/ +int main(int argc, char *argv[]) { + int size, thread_count; + + // Initiate size + if (argc <= 2) { + printf("Need 2 arguments. For file name, size, number of threads\n"); + return 0; + } + size = atoi(argv[1]); + thread_count = atoi(argv[2]); + + printf("Execution execution (processor = %d)\n", thread_count); + generateGraph(graph, size); + + printf("Writing graph to graph.txt\n"); + writeGraphToFile(graph, size); + + begin = clock(); + printf("Begin execution\n"); + + // Changing to serial execution if the processor is less or equal than 1 + if (thread_count <= 1) { + serialDijkstra(size); + } + else { + // threading started + #pragma omp parallel num_threads(thread_count) + paralelDijkstra(size); + } + end = clock(); + printf("Time elapsed: %.2f microseconds\n", ((double)(end -begin) * 1000000 / CLOCKS_PER_SEC)); + + printf("Writing result to result.txt\n"); + writeToFile(result, size); + + return 0; +} + diff --git a/src/result.txt b/src/result.txt new file mode 100644 index 0000000000000000000000000000000000000000..1b0a6a88958983145750fddd359de880ac157598 --- /dev/null +++ b/src/result.txt @@ -0,0 +1,5 @@ +0 19 20 14 21 +42 0 1 56 7 +41 37 0 55 6 +59 61 40 0 46 +66 56 25 80 0