From 13accda080c371159aab712185995ccc73270b98 Mon Sep 17 00:00:00 2001 From: 13513062 <13513062@hpc.if.itb.ac.id> Date: Fri, 19 Feb 2016 16:50:27 +0700 Subject: [PATCH] Program selesai + Laporan --- Laporan.txt | 46 ++++++++++++++++++++++++++++++++++ bucketsort | Bin 17275 -> 17715 bytes bucketsort.c | 68 +++++++++++++++++++++++++++++++++++++-------------- omp_trap | Bin 16195 -> 0 bytes 4 files changed, 96 insertions(+), 18 deletions(-) create mode 100644 Laporan.txt delete mode 100755 omp_trap diff --git a/Laporan.txt b/Laporan.txt new file mode 100644 index 0000000..6042a82 --- /dev/null +++ b/Laporan.txt @@ -0,0 +1,46 @@ +Berikut adalah hasil perbandingan waktu untuk masing-masing kombinasi dari jumlah elemen pada array dan jumlah elemen proses : + + N = Jumlah elemen pada array + M = Jumlah thread + W = Waktu, dalam detik + + +Untuk N = 50.000 + + M = 1 W = 0.903954 + M = 8 W = 0.212713 + M = 16 W = 0.211205 + M = 32 W = 0.211240 + M = 64 W = 0.214821 + M = 128 W = 0.219549 + +Untuk N = 100.000 + + M = 1 W = 3.168612 + M = 8 W = 0.751038 + M = 16 W = 0.755312 + M = 32 W = 0.755973 + M = 64 W = 0.756779 + M = 128 W = 0.733448 + +Untuk N = 200.000 + + M = 1 W = 13.197695 + M = 8 W = 2.637561 + M = 16 W = 2.638672 + M = 32 W = 2.636348 + M = 64 W = 2.700888 + M = 128 W = 2.686167 + +Untuk N = 400.000 + + M = 1 W = 49.165459 + M = 8 W = 10.203683 + M = 16 W = 10.187924 + M = 32 W = 10.457075 + M = 64 W = 10.231239 + M = 128 W = 10.303235 + + +M. Fauzan Naufan / 13513062 +Faisal Prabowo / 13513094 diff --git a/bucketsort b/bucketsort index 30c779d81839b6096c28280ea3e417c2bfde64cc..e0ef26825401e5d6489069668658bd9ec6fff400 100755 GIT binary patch delta 5127 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 delta 4291 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 V(P8N;oRdTKMFmC0zUqqe?7wv-fX@H` diff --git a/bucketsort.c b/bucketsort.c index 1c403fa..c338d42 100644 --- a/bucketsort.c +++ b/bucketsort.c @@ -2,7 +2,7 @@ #include <stdlib.h> #include <omp.h> #include <assert.h> -#include <time.h> +#include <sys/time.h> float *create_rand_nums(int num_elements) { float *rand_nums = (float *)malloc(sizeof(float) * num_elements); @@ -19,7 +19,7 @@ float * Sort(float * unsorted) { int size = unsorted[0]; float t; - for (c=1;c<size; c++) { + for (c=1;c<size + 1; c++) { d = c; while (d > 1 && unsorted[d] < unsorted[d-1]) { @@ -35,15 +35,19 @@ float * Sort(float * unsorted) { } float * * Scatter (float * input, int size) { - int * min_limit = (int *)malloc(sizeof(int) * 5); - int * max_limit = (int *)malloc(sizeof(int) * 5); - float * * output = (float **)malloc(sizeof(float*) * 400000); + float * min_limit = (float *)malloc(sizeof(float) * 5); + float * max_limit = (float *)malloc(sizeof(float) * 5); + float * * output = malloc(sizeof(float*) * 5); + + for (int i = 0; i < 5 ; i++) { + output[i] = malloc(sizeof(float) * 400000); + } //define the border limit int i; for (i = 0 ;i < 5; i++) { - min_limit[i] = 10 * i + 0 ; - max_limit[i] = 10 * i + 9 ; + min_limit[i] = i * 0.2 ; + max_limit[i] = (i+1) * 0.2 ; } //define the size of every bucket, the first index of the array is the size @@ -54,23 +58,23 @@ float * * Scatter (float * input, int size) { //scatter the input into 5 bucket int index =0; for ( i = 0; i < size ; i++) { - if (input[i] < max_limit[0]) { + if (input[i] <= max_limit[0]) { output[0][0]++; index = output[0][0]; - output[0][index] = input[i]; - } else if ((input[i] < max_limit[1]) && (input[i] > min_limit[1])) { + output[0][index] = input[i]; + } else if ((input[i] <= max_limit[1]) && (input[i] > min_limit[1])) { output[1][0]++; index = output[1][0]; output[1][index] = input[i]; - } else if ((input[i] < max_limit[2]) && (input[i] > min_limit[2])) { + } else if ((input[i] <= max_limit[2]) && (input[i] > min_limit[2])) { output[2][0]++; index = output[2][0]; output[2][index] = input[i]; - } else if ((input[i] < max_limit[3]) && (input[i] > min_limit[3])) { + } else if ((input[i] <= max_limit[3]) && (input[i] > min_limit[3])) { output[3][0]++; index = output[3][0]; output[3][index] = input[i]; - } else if (input[i] > min_limit[41]) { + } else { output[4][0]++; index = output[4][0]; output[4][index] = input[i]; @@ -81,26 +85,54 @@ float * * Scatter (float * input, int size) { } float** SortAllBucket(float* *arrayfloat, int M) { - float* *sortedarray; - int i=0; + int i=0; + + float * * sortedarray = malloc(sizeof(float*) * 5); + + for (int i = 0; i < 5 ; i++) { + sortedarray[i] = malloc(sizeof(float) * 400000); + } + #pragma omp parallel for shared(sortedarray, arrayfloat) private (i) num_threads(M) for (i=0;i<5;i++) { //Bucketnya ada 5 sortedarray[i] = Sort(arrayfloat[i]); } + + return sortedarray; } -float BucketSort(float* arrayfloat, int N, int M) { +float BucketSort(float *arrayfloat, int N, int M) { struct timeval start,end; - gettimeofday(&start, NULL); + gettimeofday(&start, NULL); float** array1 = Scatter(arrayfloat,N); - /*float** sortedarray = SortAllBucket(array1, M);*/ + float** sortedarray = SortAllBucket(array1, M); + + //gather all bucket + int element = 0; + float * gathered = malloc(sizeof(float) * 400000); + for (int i = 0; i < 5; i++) { + for (int j = 1; j <= sortedarray[i][0]; j++) { + gathered[element] = sortedarray[i][j]; + element++; + } + } + + int error = 0; + float temp = 0; + + for (int i = 0; i < N ; i++) { + if (gathered[i] < temp) error++; + temp = gathered[i]; + } + printf("Error : %d\n",error); gettimeofday(&end, NULL); float delta = ((end.tv_sec - start.tv_sec)*1000000u + end.tv_usec - start.tv_usec) / 1.e6; + return delta; } diff --git a/omp_trap b/omp_trap deleted file mode 100755 index 6dd9157fc98d0e2800bebc67c612c7cd6f75be1a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16195 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 A$p8QV -- GitLab