From a1433fa640fb0925f7c9fd5329f79dfa67fc18c1 Mon Sep 17 00:00:00 2001 From: gazandic <gazandic@gmail.com> Date: Fri, 19 Feb 2016 14:10:42 +0700 Subject: [PATCH] openmp work --- bucket_sort.c | 177 ++++++++++++++++++++++++++++++++------------------ bucketsort.c | 130 ------------------------------------ main | Bin 16792 -> 0 bytes 3 files changed, 114 insertions(+), 193 deletions(-) delete mode 100644 bucketsort.c delete mode 100755 main diff --git a/bucket_sort.c b/bucket_sort.c index 1c0b4ff..151d166 100644 --- a/bucket_sort.c +++ b/bucket_sort.c @@ -3,7 +3,7 @@ #include <time.h> #include <omp.h> #include <assert.h> - +#include <time.h> int *create_rand_nums(int num_elements) { int *rand_nums = (int *)malloc(sizeof(int) * num_elements); assert(rand_nums != NULL); @@ -16,79 +16,130 @@ int *create_rand_nums(int num_elements) { int main(int argc, char** argv) { if (argc != 3) { - fprintf(stderr, "Usage: avg num_elements nuim_thread\n"); + fprintf(stderr, "Usage: avg num_elements num_threads\n"); + exit(1); } + //MPI_Status Stat; srand(time(NULL)); - int world_rank; - int thread_count; - int position=0, order=0; - int i, j, k, l, t, rc, max = -RAND_MAX, min = RAND_MAX; + //MPI_Init(NULL, NULL); + + //int world_rank; + //MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); + //int world_size; + //MPI_Comm_size(MPI_COMM_WORLD, &world_size); + + int i, j, k, l, max = -RAND_MAX, min = RAND_MAX; int total_elements = atoi(argv[1]); int range; - - int my_rank; - thread_count = atoi(argv[2]); - - - int inmsg[total_elements]; - int bucket[total_elements]; + int world_size = atoi(argv[2]); + //int inmsg[total_elements]; + int bucket[world_size][total_elements]; int *rand_nums = NULL; - - double time_start, time_stop; - - rand_nums = create_rand_nums(total_elements); - for (i = 0; i < total_elements; i++) { - if (rand_nums[i] > max) - max = rand_nums[i]; - if (rand_nums[i] < min) - min = rand_nums[i]; - } - range = (max - min) / thread_count + ((max - min) % thread_count > 0); - //time_start = MPI_Wtime(); - //bucketing - #pragma omp parallel num_threads(thread_count,position,order) shared(rand_nums) private(bucket,i,j,k,my_rank) - my_rank = omp_get_thread_num(); - for (j = 0; j < total_elements; j++) { - if ((rand_nums[j] < my_rank * range + range) && (rand_nums[j] >= my_rank * range)) { - bucket[i] = rand_nums[j]; - i++; - } - } - for (l = i; l < total_elements; l++) { - bucket[l] = RAND_MAX; - } - - //Sort - for (k = 0; k < i-1; k++) - for (j = k+1; j < i; j++) - if (bucket[k] > bucket[j]) { - int temp = bucket[k]; - bucket[k] = bucket[j]; - bucket[j] = temp; + clock_t time_start, time_stop; + time_start = clock(); + // if (world_rank == 0) { + rand_nums = create_rand_nums(total_elements); + for (i = 0; i < total_elements; i++) { + if (rand_nums[i] > max) + max = rand_nums[i]; + if (rand_nums[i] < min) + min = rand_nums[i]; + printf("%d ",rand_nums[i]); + } + printf("\n"); + range = (max - min) / world_size + ((max - min) % world_size > 0); + //time_start = MPI_Wtime(); + for (i = 0; i < world_size; i++) { + k = 0; + for (j = 0; j < total_elements; j++) { + if ((rand_nums[j] < i*range+range) && (rand_nums[j] >= i*range)) { + bucket[i][k] = rand_nums[j]; + k++; + } + } + for (l = k; l < total_elements; l++) { + bucket[i][l] = -1; + } + //rc = MPI_Send(bucket[i], total_elements+1, MPI_INT, i, 1, MPI_COMM_WORLD); } - while (order != my_rank); - - #pragma omp critical - - for (j = 0; j < total_elements; j++) { - if (bucket[j] >= 0) { - if (bucket[j] < RAND_MAX) { - rand_nums[position] = bucket[j]; - position++; + for (i = 1 ; i < total_elements-1; i++)// { + for (j = i; j < total_elements; j++) + if (bucket[0][i] > bucket[0][j]) { + int temp = bucket[0][i]; + bucket[0][i] = bucket[0][j]; + bucket[0][j] = temp; + } + /*j = i; + + while ( j > 0 && bucket[0][j] < bucket[0][j-1]) { + t = bucket[0][j]; + bucket[0][j] = bucket[0][j-1]; + bucket[0][j-1] = t; + + j--; + } + }*/ + // } else { + //rc = MPI_Recv(inmsg, total_elements+1, MPI_INT, 0, 1, MPI_COMM_WORLD, &Stat); + //Sort + int thread_count = strtol(argv[2], NULL, 10); + #pragma omp parallel for num_threads(thread_count) + for(k=0;k<world_size;k++) + for (i = 0; i < total_elements-1; i++) + for (j = i+1; j < total_elements; j++) + if (bucket[k][i] > bucket[k][j]) { + int temp = bucket[k][i]; + bucket[k][i] = bucket[k][j]; + bucket[k][j] = temp; + } + /* for (i = 1 ; i < total_elements; i++) { + j = i; + + while ( j > 0 && inmsg[j] < inmsg[j-1]) { + t = inmsg[j]; + inmsg[j] = inmsg[j-1]; + inmsg[j-1] = t; + + j--; + } + } */ + //rc = MPI_Send(inmsg, total_elements+1, MPI_INT, 0, 1, MPI_COMM_WORLD); + // } + // if (world_rank == 0) { + k = 0; + for (j = 0; j < total_elements; j++) { + if (bucket[0][j] >= 0) { + rand_nums[k] = bucket[0][j]; + k++; } } - } - //time_stop = MPI_Wtime() - time_start; - - if (my_rank == 3) { - for(j=0;j<total_elements;j++){ - printf("%d",rand_nums[j]); + for (i = 1; i < world_size; i++) { + // rc = MPI_Recv(bucket[i], total_elements+1, MPI_INT, i, 1, MPI_COMM_WORLD, &Stat); + for (j = 0; j < total_elements; j++) { + if (bucket[i][j] >= 0) { + rand_nums[k] = bucket[i][j]; + k++; + } + } } - free(rand_nums); - - //printf("%d processes, %d elements, %.2lf seconds", thread_count, total_elements, time_stop); + // time_stop = MPI_Wtime() - time_start; + + for(i=0;i<total_elements;i++){ + printf("%d ",rand_nums[i]); } + printf("\n"); + time_stop = clock(); + double waktu = (double) (time_stop - time_start) / CLOCKS_PER_SEC; + //if (world_rank == 0) { + free(rand_nums); + printf("%d processes, %d elements, %.2lf seconds", world_size, total_elements, waktu); + //} + + // MPI_Barrier(MPI_COMM_WORLD); + // MPI_Finalize(); } + + diff --git a/bucketsort.c b/bucketsort.c deleted file mode 100644 index 8f7c19e..0000000 --- a/bucketsort.c +++ /dev/null @@ -1,130 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <time.h> -#include <mpi.h> -#include <assert.h> - -int *create_rand_nums(int num_elements) { - int *rand_nums = (int *)malloc(sizeof(int) * num_elements); - assert(rand_nums != NULL); - int i; - for (i = 0; i < num_elements; i++) { - rand_nums[i] = rand() % num_elements; - } - return rand_nums; -} - -int main(int argc, char** argv) { - if (argc != 3) { - fprintf(stderr, "Usage: avg num_elements num_thread\n"); - } - - int world_rank; - - int i, j, k, l, t, rc, max = -RAND_MAX, min = RAND_MAX; - int total_element = atoi(argv[1]); - int total_thread = atoi(argv[2]); - int range; - - int inmsg[total_elements]; - int bucket[total_elements]; - int *rand_nums = NULL; - - //double time_start, time_stop; - //if (world_rank == 0) { - rand_nums = create_rand_nums(total_elements); - for (i = 0; i < total_elements; i++) { - if (rand_nums[i] > max) - max = rand_nums[i]; - if (rand_nums[i] < min) - min = rand_nums[i]; - } - range = (max - min) / total_thread + ((max - min) % total_thread > 0); - //time_start = MPI_Wtime(); - -# pragma omp parallel for schedule(static) default(none) \ - shared(rand_nums) private(i, bucket, j,k) \ num_threads(thread_count) - - - - for (i = 0; i < total_thread; i++) { - k = 0; - for (j = 0; j < total_elements; j++) { - if ((rand_nums[j] < i*range+range) && (rand_nums[j] >= i*range)) { - bucket[k] = rand_nums[j]; - k++; - } - } - for (l = k; l < total_elements; l++) { - bucket[l] = -1; - } - //rc = MPI_Send(bucket[i], total_elements+1, MPI_INT, i, 1, MPI_COMM_WORLD); - } - for (i = 1 ; i < total_elements-1; i++)// { - for (j = i; j < total_elements; j++) - if (bucket[i] > bucket[j]) { - int temp = bucket[i]; - bucket[i] = bucket[j]; - bucket[j] = temp; - } - /*j = i; - - while ( j > 0 && bucket[0][j] < bucket[0][j-1]) { - t = bucket[0][j]; - bucket[0][j] = bucket[0][j-1]; - bucket[0][j-1] = t; - - j--; - } - }*/ - //} else { - //rc = MPI_Recv(inmsg, total_elements+1, MPI_INT, 0, 1, MPI_COMM_WORLD, &Stat); - //Sort - for (i = 0; i < total_elements-1; i++) - for (j = i+1; j < total_elements; j++) - if (bucket[i] > bucket[j]) { - int temp = bucket[i]; - bucket[i] = bucket[j]; - bucket[j] = temp; - } - /* for (i = 1 ; i < total_elements; i++) { - j = i; - - while ( j > 0 && inmsg[j] < inmsg[j-1]) { - t = inmsg[j]; - inmsg[j] = inmsg[j-1]; - inmsg[j-1] = t; - - j--; - } - } */ - //rc = MPI_Send(inmsg, total_elements+1, MPI_INT, 0, 1, MPI_COMM_WORLD); - //} - //if (world_rank == 0) { - k = 0; - for (j = 0; j < total_elements; j++) { - if (bucket[j] >= 0) { - rand_nums[k] = bucket[j]; - k++; - } - } - for (i = 1; i < total_thread; i++) { - //rc = MPI_Recv(bucket[i], total_elements+1, MPI_INT, i, 1, MPI_COMM_WORLD, &Stat); - for (j = 0; j < total_elements; j++) { - if (bucket[j] >= 0) { - rand_nums[k] = bucket[j]; - k++; - } - } - } - //time_stop = MPI_Wtime() - time_start; - - //} - //if (world_rank == 0) { - free(rand_nums); - printf("%d processes, %d elements, %.2lf seconds", total_thread, total_elements/*, time_stop*/); - //} - -} - - diff --git a/main b/main deleted file mode 100755 index 91b7da3fb8bdd7a99ad1da4ae86fdf1906010917..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16792 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 -- GitLab