From 5c0069d7e9c335fa65d997785f5a8c50f3b02dd5 Mon Sep 17 00:00:00 2001 From: Ahmad Aidin <ahmadaidin08.aa@gmail.com> Date: Tue, 29 May 2018 14:05:23 +0700 Subject: [PATCH] done --- bucketsort.c | 178 ++++++++++++++++++++++++++++++++++++++------------- omp_trap.c | 12 ++-- test | Bin 0 -> 17648 bytes 3 files changed, 140 insertions(+), 50 deletions(-) create mode 100644 test diff --git a/bucketsort.c b/bucketsort.c index 59e1827..330e20d 100644 --- a/bucketsort.c +++ b/bucketsort.c @@ -6,25 +6,33 @@ #include <time.h> #include <assert.h> +typedef struct{ + int* content; + int size; + int nContent; +} Bucket; + +typedef struct{ + Bucket* tables; +} arrayBucket; + +Bucket bucketsort(arrayBucket localArray, int nBucket, int size); -int* bucket(int* localArray, int n, ); -using namespace std; int main( int argc, char* argv[] ) { - double start_time, end_time; - int i, j, a, b, temp; - + double start_time, nContent_time; + if (argc != 2) { fprintf(stderr, "usage: %s <number of threads>\n", argv[0]); exit(0); } - - thread_count = strtol(argv[1], NULL, 10); - + + int thread_count = strtol(argv[1], NULL, 10); + int size; scanf("%d", &size); - int *array = malloc(sizeof( int) * size); - for (i=0;i<size;i++) + int *array = (int*)malloc(sizeof( int) * size); + for (int i=0;i<size;i++) array[i] = rand() % size; // starting time calculation of the sort @@ -32,28 +40,28 @@ int main( int argc, char* argv[] ) // min and max values are got int min = array[0]; int max = array[0]; - for(i=0; i < size; i++) { - if(array[i] < min) + for(int i=0; i < size; i++) { + if(array[i] < min) min = array[i]; - if(array[i] > max) + if(array[i] > max) max = array[i]; } - + // calculating how many numbers each bucket/process will get numbers - int *elementQtyArray = malloc (sizeof(int)*thread_count); + int *elementQtyArray = (int*)malloc (sizeof(int)*thread_count); // default values - - for(int b=1; b < thread_count; b++) { + + for(int b=0; b < thread_count; b++) { elementQtyArray[b] = 0; } - + if(thread_count>1){ int boundary1; for(int b=0; b < size; b++) { int increaseOf = max/(thread_count-1); int k = 1; boundary1 = 0; - for(j = increaseOf; j <= max; j += increaseOf) { + for(int j = increaseOf; j <= max; j += increaseOf) { if(array[b] <= j) { elementQtyArray[k]++; boundary1 = 1; @@ -65,32 +73,114 @@ int main( int argc, char* argv[] ) elementQtyArray[k-1]++; } - #pragma omp parallel num_threads(thread_count) { - - } - } - -return 0; -} + Bucket localArray[thread_count]; + for (int i = 0; i < thread_count; i++) { + /* code */ + localArray[i].size = elementQtyArray[i]; + localArray[i].content = (int*)malloc (sizeof(int)* localArray[i].size); + localArray[i].nContent = 0; + } + int increaseOf = max/(thread_count-1); + for(int b=0; b < size; b++) { + int k = 1; + int boundary1 = 0; + for(int j = increaseOf; j <= max; j += increaseOf) { + if(array[b] <= j) { + int idx=localArray[k].nContent; + localArray[k].content[idx]=array[b]; + localArray[k].nContent++; + boundary1 = 1; + break; + } + k++; + } + if (!boundary1){ + int idx=localArray[k-1].nContent; + localArray[k-1].content[idx]=array[b]; + localArray[k-1].nContent++; + } + }/* + for(int i=0; i<size; i++){ + printf("%d ", array[i]); + } + printf("\n"); + for(int i=0; i<thread_count; i++){ + printf("%d ", elementQtyArray[i]); + } + + printf("\n"); + for(int i=0; i<thread_count; i++){ + for(int j=0; j<localArray[i].size; j++){ + printf("%d ", localArray[i].content[j]); + } + } + */ + + + arrayBucket localArrayB; + localArrayB.tables = localArray; + + Bucket sortenArray; + + sortenArray = bucketsort(localArrayB, thread_count, size); + + printf("\nsortir:\n"); + for(int x=0; x<size; x++){ + printf("%d %d\n", array[x], sortenArray.content[x]); + } + +} else { -int* bucket(int* localArray, int n ){ - // --- sorting the bucket - int arraytemp[n]; - - int a, b, temp; - for (a = 1 ; a <= n - 1; a++) { - b = a; - while ( b > 0 && localArray[b] < localArray[b-1]) { - temp = localArray[b]; - localArray[b] = localArray[b-1]; - localArray[b-1] = temp; - b--; - } - } - for (a=0; a<n; a++){ - arraytemp[a] = localArray[a]; - } - return arraytemp; } +return 0; +} + + +Bucket bucketsort(arrayBucket localArrayB, int nBucket,int size){ + Bucket sortenArray; + sortenArray.content= (int*)malloc (sizeof(int)* size); + sortenArray.nContent=0; + sortenArray.size=size; + + + int a, b, temp, idx, i, idxAfter; + int bucket_num; + int my_rank; + # pragma omp parallel for schedule(static) default(none) \ + shared(sortenArray, localArrayB, nBucket) private(my_rank, i,a, b, bucket_num, temp, idx, idxAfter) num_threads(nBucket) + for(bucket_num=0; bucket_num<nBucket; bucket_num++){ + my_rank = omp_get_thread_num(); + if(bucket_num==my_rank){ + printf("oke %d %d\n", bucket_num, my_rank); + for (a = 1 ; a <localArrayB.tables[bucket_num].size; a++) { + b = a; + while ( b > 0 && localArrayB.tables[bucket_num].content[b] < localArrayB.tables[bucket_num].content[b-1]) { + temp = localArrayB.tables[bucket_num].content[b]; + localArrayB.tables[bucket_num].content[b] = localArrayB.tables[bucket_num].content[b-1]; + localArrayB.tables[bucket_num].content[b-1] = temp; + b++; + } + } + if(bucket_num!=0){ + idx= localArrayB.tables[bucket_num-1].size; + } else { + idx=0; + } + + idxAfter=idx+localArrayB.tables[bucket_num].size; + + for(a=idx; a<idxAfter; a++){ + i=0; + sortenArray.content[a]=localArrayB.tables[bucket_num].content[i]; + sortenArray.nContent++; + printf("%d %d\n", localArrayB.tables[bucket_num].content[i],sortenArray.content[a]); + i++; + } + } + } + + # pragma omp barrier + return sortenArray; +} diff --git a/omp_trap.c b/omp_trap.c index c0779f2..94fae60 100644 --- a/omp_trap.c +++ b/omp_trap.c @@ -1,7 +1,7 @@ -/* +/* * Copyrights http://www.cs.usfca.edu/~peter/cs625/code/trap/omp_trap.c * File: omp_trap.c - * Purpose: Calculate definite integral using trapezoidal + * Purpose: Calculate definite integral using trapezoidal * rule. * * Input: a, b, n @@ -12,7 +12,7 @@ * gcc -g -Wall -fopenmp -o omp_trap omp_trap.c * Usage: ./omp_trap <number of threads> * - * Notes: + * Notes: * 1. The function f(x) is hardwired. * 2. This version uses OpenMP's parallel for with variable * scope specified, and static partitioning. @@ -41,7 +41,7 @@ int main(int argc, char* argv[]) { printf("Enter a, b, and n\n"); scanf("%lf %lf %d", &a, &b, &n); - + /* OpenMP starts from here */ integral = Trap(a, b, n); @@ -55,7 +55,7 @@ int main(int argc, char* argv[]) { /*------------------------------------------------------------------ * Function: Trap * Purpose: Use trapezoidal rule to compute definite integral - * Input args: + * Input args: * a: left endpoint * b: right endpoint * n: number of trapezoids @@ -63,7 +63,7 @@ int main(int argc, char* argv[]) { */ double Trap(double a, double b, int n) { double h, x, integral = 0.0; - int i; + int i; h = (b-a)/n; integral += (f(a) + f(b))/2.0; diff --git a/test b/test new file mode 100644 index 0000000000000000000000000000000000000000..0510b595b0934d2b1fcf6f91c7d1f0865be0aa18 GIT binary patch literal 17648 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 NSHs#e3Ny@M{|h9m>tz4{ literal 0 HcmV?d00001 -- GitLab