diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..600d2d33badf45cc068e01d2e3c837e11c417bc4 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.vscode \ No newline at end of file diff --git a/parallel.cu b/parallel.cu new file mode 100644 index 0000000000000000000000000000000000000000..9bb73d092fb4412851ea9806c39fc3281680f68f --- /dev/null +++ b/parallel.cu @@ -0,0 +1,184 @@ +#include <stdio.h> +#include <stdlib.h> +#include <limits.h> +#include <time.h> +#include <omp.h> + +#define TRUE 1 +#define FALSE 0 +#define INF LONG_MAX +// #define N_THREADS 10 +#define OUTPUT_FILE_PATH "parallel_result.txt" + +void print_matrix(long matrix[], int n_row, int n_col); +void print_array(long arr[], int len); +long *initialize_matrix(int random_number, int n); +long *initialize_result(int n); +void write_output(long matrix[], int n_row, int n_col, double time); + +__global__ +void dijkstra(int n, long matrix[], long result[]) { + printf("Djikstra summoned"); + + long *connected; // Array of 'boolean' on whether vertice [i] is connected to source + long *distance; // Distance of vertice [i] from source + + int my_rank = blockIdx.x * blockDim.x + threadIdx.x; + int stride = blockDim.x * gridDim.x; + + connected = (long*)malloc(n * sizeof(long)); + distance = (long *)malloc(n * sizeof(long)); + + printf("rank %d of n %d", my_rank, n); + + for (int SOURCE_V = my_rank; SOURCE_V < n; SOURCE_V += stride) { + printf("Now processing for vertice %d.", SOURCE_V); + + for (int i = 0; i < n; i++) { + if (i == SOURCE_V) { + connected[i] = TRUE; + } else { + connected[i] = FALSE; + } + } + + for (int i = 0; i < n; i++) { + distance[i] = matrix[SOURCE_V * n + i]; + } + + /* Djikstra */ + for (int i = 1; i < n; i++) { + + long min_dist = INF; + int closest_v = -1; + for (int i = 0; i < n; i++) { + if (connected[i] != TRUE) { + if (distance[i] < min_dist) { + min_dist = distance[i]; + closest_v = i; + } + } + } + + //printf("Closest vertice is: %d\n", closest_v); + connected[closest_v] = TRUE; + + /* Update distances */ + /* With unconnected vertices in distance array */ + for (int j = 0; j < n; j++) { + if (connected[j] == FALSE) { + /* If not connected, only concern with distance array */ + long new_dist = distance[closest_v] + matrix[closest_v * n + j]; + if (new_dist < distance[j]) { + distance[j] = new_dist; + } + } + } + for (int j = 0; j < n; j++) { + result[SOURCE_V * n + j] = distance[j]; + } + } + } + + free(connected); + free(distance); +} + +int main (int argc, char **argv) { + long *matrix, *result; // Matrix size i * j of distance from vertice [i] to vertice [j] + int n; // Number of vertices + // int my_rank, thread_count, sub_n; + clock_t start, end; + double cpu_time_used; + + /* Read number of vertices */ + printf("Number of vertices (n): "); scanf("%d", &n); + + cudaMallocManaged(&matrix, n*sizeof(long)); + cudaMallocManaged(&result, n*sizeof(long)); + + matrix = initialize_matrix(13517142, n); + printf("\nGenerated %d * %d matrix.\n", n, n); + + print_matrix(matrix, n, n); + + result = initialize_result(n); + + start = clock(); + + dijkstra<<<1,1>>>(n, matrix, result); + + cudaDeviceSynchronize(); + + end = clock(); + cpu_time_used = (((double) (end - start)) / CLOCKS_PER_SEC) * 1000000; + write_output(result, n, n, cpu_time_used); + printf("\nResults written to %s.\n", OUTPUT_FILE_PATH); + + cudaFree(result); + cudaFree(matrix); +} + +void print_matrix(long matrix[], int n_row, int n_col) { + for (int i = 0; i < n_row; i++) { + for (int j = 0; j < n_col; j++) { + printf("%ld ", matrix[i * n_col + j]); + } + printf("\n"); + } +} + +void print_array(long arr[], int len) { + for (int i = 0; i < len; i++) { + printf("%ld ", arr[i]); + } + printf("\n"); +} + +void write_output(long matrix[], int n_row, int n_col, double time) { + FILE * file; + file = fopen (OUTPUT_FILE_PATH,"w"); + for (int i = 0; i < n_row; i++) { + for (int j = 0; j < n_col; j++) { + fprintf(file, "%ld ", matrix[i * n_col + j]); + } + fprintf(file, "\n"); + } + fprintf(file, "Process finished in %f microseconds.\n", time); + fclose (file); +} + +long *initialize_matrix(int random_number, int n) { + /* Initialize variables */ + long *matrix = (long *)malloc(sizeof(long) * n*n); + + srand(random_number); + for (int i = 0; i < n; i++) { + for (int j = 0; j <= i; j++) { + if (i == j) { + matrix[i * n + j] = 0; + } else { + long dist = (rand() % 9) + 1; + matrix[i * n + j] = dist; + matrix[j * n + i] = dist; + } + } + } + return matrix; +} + +long *initialize_result(int n) { + long *result = (long *)malloc(sizeof(long) * n*n); + + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (i == j) { + result[i * n + j] = 0; + } else { + result[i * n + j] = INF; + } + } + } + + return result; +} \ No newline at end of file diff --git a/serial.c b/serial.c new file mode 100644 index 0000000000000000000000000000000000000000..99e470f8b03b8d80eee04064b65f6bf84dd2ad5a --- /dev/null +++ b/serial.c @@ -0,0 +1,199 @@ +#include <stdio.h> +#include <stdlib.h> +#include <limits.h> +#include <time.h> + +#define TRUE 1 +#define FALSE 0 +#define INF LONG_MAX +#define OUTPUT_FILE_PATH "serial_result.txt" + +void print_matrix(long matrix[], int n_row, int n_col); +void print_array(long arr[], int len); +int idx_min_distance(long connd[], long dist[], int len); +long *initialize_matrix(int random_number, int n); +long *initialize_result(int n); +void write_output(long matrix[], int n_row, int n_col, double time); + +int main (int argc, char **argv) { + long *matrix, *result; // Matrix size i * j of distance from vertice [i] to vertice [j] + long *connected; // Array of 'boolean' on whether vertice [i] is connected to source [0] + long *distance; // Distance of vertice [i] from source [0] + int n; // Number of vertices + + /* Read number of vertices */ + printf("Number of vertices (n): "); scanf("%d", &n); + + matrix = initialize_matrix(13517142, n); + printf("\nGenerated %d * %d matrix.\n", n, n); + //print_matrix(matrix, n, n); + + result = initialize_result(n); + connected = malloc(n * sizeof(long)); + distance = malloc(n * sizeof(long)); + + clock_t start, end; + double cpu_time_used; + start = clock(); + + for (int SOURCE_V = 0; SOURCE_V < n; SOURCE_V++) { + for (int i = 0; i < n; i++) { + if (i == SOURCE_V) { + connected[i] = TRUE; + } else { + connected[i] = FALSE; + } + } + + for (int i = 0; i < n; i++) { + distance[i] = matrix[SOURCE_V * n + i]; + } + + /* Djikstra */ + for (int i = 1; i < n; i++) { + //printf("------------------------------------------------\n"); + //printf("CONNECTED : "); + //print_array(connected, n); + //printf("DISTANCE FROM %d : ", SOURCE_V); + //print_array(distance, n); + + int closest_v = idx_min_distance(connected, distance, n); + //printf("Closest vertice is: %d\n", closest_v); + connected[closest_v] = TRUE; + + /* Update distances */ + /* With unconnected vertices in distance array */ + for (int j = 0; j < n; j++) { + if (connected[j] == FALSE) { + /* If not connected, only concern with distance array */ + long new_dist = distance[closest_v] + matrix[closest_v * n + j]; + if (new_dist < distance[j]) { + distance[j] = new_dist; + } + } + } + + /* With connected vertices in result matrix */ + /* int closest_to_closest_v = SOURCE_V; + if (distance[closest_v] != matrix[closest_v * n + SOURCE_V]) { + for (int i = 0; i < n; i++) { + if (connected[i] == TRUE && i != closest_v) { + long dist_closest_to_v = matrix[closest_v * n + closest_to_closest_v]; + long i_to_v = matrix[closest_v * n + i]; + if (i_to_v < dist_closest_to_v) { + closest_to_closest_v = i; + } + } + } + result[closest_v * n + closest_to_closest_v] = matrix[closest_v * n + closest_to_closest_v]; + result[closest_to_closest_v * n + closest_v] = matrix[closest_v * n + closest_to_closest_v]; + } + result[closest_v * n + SOURCE_V] = distance[closest_v]; + result[SOURCE_V * n + closest_v] = distance[closest_v]; + for (int i = 0; i < n; i++) { + if (connected[i] == TRUE && i != closest_v && i != closest_to_closest_v) { + result[closest_v * n + i] = distance[closest_v] + distance[i]; + result[i * n + closest_v] = distance[closest_v] + distance[i]; + } + }*/ + } + + for (int j = 0; j < n; j++) { + result[SOURCE_V * n + j] = distance[j]; + } + } + + //printf("\n----------------------RESULTS---------------------\n", n, n); + //print_matrix(result, n, n); + end = clock(); + cpu_time_used = (((double) (end - start)) / CLOCKS_PER_SEC) * 1000000; + //cpu_time_used = (end - start); + write_output(result, n, n, cpu_time_used); + printf("\nResults written to %s.\n", OUTPUT_FILE_PATH); + + /* Deallocation */ + free(matrix); + free(result); + free(connected); + free(distance); +} + +void print_matrix(long matrix[], int n_row, int n_col) { + for (int i = 0; i < n_row; i++) { + for (int j = 0; j < n_col; j++) { + printf("%ld ", matrix[i * n_col + j]); + } + printf("\n"); + } +} + +void print_array(long arr[], int len) { + for (int i = 0; i < len; i++) { + printf("%ld ", arr[i]); + } + printf("\n"); +} + +int idx_min_distance(long connd[], long dist[], int len) { + long min_dist = INF; + int idx_min_dist = -1; + for (int i = 0; i < len; i++) { + if (connd[i] != TRUE) { + if (dist[i] < min_dist) { + min_dist = dist[i]; + idx_min_dist = i; + } + } + } + return idx_min_dist; +} + +void write_output(long matrix[], int n_row, int n_col, double time) { + FILE * file; + file = fopen (OUTPUT_FILE_PATH,"w"); + for (int i = 0; i < n_row; i++) { + for (int j = 0; j < n_col; j++) { + fprintf(file, "%ld ", matrix[i * n_col + j]); + } + fprintf(file, "\n"); + } + fprintf(file, "Process finished in %f microseconds.\n", time); + fclose (file); +} + + +long *initialize_matrix(int random_number, int n) { + /* Initialize variables */ + long *matrix = malloc(sizeof(long) * n*n); + + srand(random_number); + for (int i = 0; i < n; i++) { + for (int j = 0; j <= i; j++) { + if (i == j) { + matrix[i * n + j] = 0; + } else { + long dist = rand(); + matrix[i * n + j] = dist; + matrix[j * n + i] = dist; + } + } + } + + return matrix; +} + +long *initialize_result(int n) { + long *result = malloc(sizeof(long) * n*n); + + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (i == j) { + result[i * n + j] = 0; + } else { + result[i * n + j] = INF; + } + } + } + + return result; +} \ No newline at end of file