diff --git a/bucketsort.c b/bucketsort.c index fa029e2f6118b36106e12e6d4b80ebd731bebf2d..b31b2ed8f9cfbf69a50944e42b27d4f644a34edf 100644 --- a/bucketsort.c +++ b/bucketsort.c @@ -1,82 +1,130 @@ -// Copyright 2012 www.mpitutorial.com - -// Program yang menghitung rata rata dari array secara paralel menggunakan scatter dan gather +// Copyright www.computing.llnl.gov #include <stdio.h> #include <stdlib.h> #include <time.h> #include <mpi.h> #include <assert.h> - + float *create_rand_nums(int num_elements) { - float *rand_nums = (float *)malloc(sizeof(float) * num_elements); - assert(rand_nums != NULL); - int i; - for (i = 0; i < num_elements; i++) { - rand_nums[i] = (rand() / (float)RAND_MAX); - } - return rand_nums; -} - -float compute_avg(float *array, int num_elements) { - float sum = 0.f; - int i; - for (i = 0; i < num_elements; i++) { - sum += array[i]; - } - return sum / num_elements; -} + float *rand_nums = (float *)malloc(sizeof(float) * num_elements); + assert(rand_nums != NULL); + int i; + for (i = 0; i < num_elements; i++) { + rand_nums[i] = rand() % num_elements; + } + return rand_nums; +} + +void insertion_sort(float *array, int num_elements) { + int d, c, temp; + for (c = 1; c < num_elements; c++) { + d = c; + while (d > 0 && array[d] < array[d-1]) { + temp = array[d]; + array[d] = array[d-1]; + array[d-1] = temp; + d--; + } + } +} -int main(int argc, char** argv) { - if (argc != 2) { - fprintf(stderr, "Usage: avg num_elements_per_proc\n"); - exit(1); - } - - int num_elements_per_proc = atoi(argv[1]); - srand(time(NULL)); - - 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); - - float *rand_nums = NULL; - if (world_rank == 0) { - rand_nums = create_rand_nums(num_elements_per_proc * world_size); - } - - float *sub_rand_nums = (float *)malloc(sizeof(float) * - num_elements_per_proc); - assert(sub_rand_nums != NULL); - - MPI_Scatter(rand_nums, num_elements_per_proc, MPI_FLOAT, sub_rand_nums, - num_elements_per_proc, MPI_FLOAT, 0, MPI_COMM_WORLD); - - float sub_avg = compute_avg(sub_rand_nums, num_elements_per_proc); - - float *sub_avgs = NULL; - if (world_rank == 0) { - sub_avgs = (float *)malloc(sizeof(float) * world_size); - assert(sub_avgs != NULL); - } - MPI_Gather(&sub_avg, 1, MPI_FLOAT, sub_avgs, 1, MPI_FLOAT, 0, - MPI_COMM_WORLD); - - if (world_rank == 0) { - float avg = compute_avg(sub_avgs, world_size); - printf("Avg of all elements is %f\n", avg); - } - - if (world_rank == 0) { - free(rand_nums); - free(sub_avgs); - } - free(sub_rand_nums); - - MPI_Barrier(MPI_COMM_WORLD); - MPI_Finalize(); -} +int main(int argc, char *argv[]) { + const int BUCKET_HEADER = 1; + const int BUCKET_BODY = 2; + + int i,j; + int num_elements = atoi(argv[1]); + + MPI_Status Stat; + MPI_Init(NULL, NULL); + + int world_size; + MPI_Comm_size(MPI_COMM_WORLD, &world_size); + + int world_rank; + MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); + + int bucket_range = num_elements / world_size; + float bucket[world_size][num_elements]; + int count[world_size]; + + // Buat elemen randomm + if (world_rank == 0) { + float *rand_nums = NULL; + rand_nums = create_rand_nums(num_elements); + + // Bagi elemen tersebut ke dalam bucket + for (i = 0; i < world_size; ++i) { + for (j = 0; j < num_elements; ++j) { + bucket[i][j] = -1; + } + } + + for (i = 0; i < world_size; ++i) { + count[i] = 0; + } + + for (i = 0; i < num_elements; ++i) { + int idx = (int) rand_nums[i]/bucket_range; + bucket[idx][count[idx]] = rand_nums[i]; + count[idx]++; + } + + // Kirim bucket ke proses yang sesuai + for (i = 0; i < world_size; ++i) { + // Kirim ukuran bucket + int size = count[i]; + MPI_Send(&size, 1, MPI_INT, i, BUCKET_HEADER, MPI_COMM_WORLD); + + // Kirim isi bucket + MPI_Send(bucket[i], count[i], MPI_FLOAT, i, BUCKET_BODY, MPI_COMM_WORLD); + } + + } + + // Ambil bucket yang dikirim oleh proses utama + int bucket_size; + MPI_Recv(&bucket_size, 1, MPI_INT, 0, BUCKET_HEADER, MPI_COMM_WORLD, &Stat); + + float *my_bucket = (float *)malloc(sizeof(float) * bucket_size); + MPI_Recv(my_bucket, bucket_size, MPI_FLOAT, 0, BUCKET_BODY, MPI_COMM_WORLD, &Stat); + + // Urutkan my_bucket yang ada di tiap proses + insertion_sort(my_bucket, bucket_size); + + // printf("From procces %d\n", world_rank); + // for (i = 0; i < bucket_size; i++) { + // printf("elemen ke-%d: %f\n", i, my_bucket[i]); + // } + + // Kirim kembali my_bucket yang terurut ke proses 0 + MPI_Send(&bucket_size, 1, MPI_INT, 0, BUCKET_HEADER, MPI_COMM_WORLD); + MPI_Send(my_bucket, bucket_size, MPI_FLOAT, 0, BUCKET_BODY, MPI_COMM_WORLD); + + // Gabungkan my_bucket menjadi satu array + if (world_rank == 0) { + float *sorted_array = (float *)malloc(sizeof(float) * num_elements); + int counter = 0; + + for (i = 0; i < world_size; ++i) { + int recv_bucket_size; + MPI_Recv(&recv_bucket_size, 1, MPI_INT, i, BUCKET_HEADER, MPI_COMM_WORLD, &Stat); + + float* recv_bucket = (float *)malloc(sizeof(float) * bucket_size); + MPI_Recv(recv_bucket, bucket_size, MPI_FLOAT, i, BUCKET_BODY, MPI_COMM_WORLD, &Stat); + + for (j = 0; j < recv_bucket_size; ++j) { + sorted_array[counter] = recv_bucket[j]; + counter++; + } + } + // Print array yang sudah terurut; + printf("Element yang sudah terurut:\n"); + for (j = 0; j < num_elements; ++j) { + printf("%f\n", sorted_array[j]); + } + } + MPI_Finalize(); +} \ No newline at end of file