diff --git a/src/change b/src/change new file mode 100644 index 0000000000000000000000000000000000000000..d78540c6dc330c412b7850b2a1bc976244ee4fc3 Binary files /dev/null and b/src/change differ diff --git a/src/change.c b/src/change.c new file mode 100644 index 0000000000000000000000000000000000000000..d77c2d9283c56dc119f69151069ebd4b04f0fe93 --- /dev/null +++ b/src/change.c @@ -0,0 +1,9 @@ +#include <stdio.h> +int main() { + const int x = 10; //define constant int + int *ptr; + printf("x = %d\n", x); + ptr = &x; //ptr points the variable x + *ptr = 15; //Updating through pointer + printf("x = %d\n", x); +} \ No newline at end of file diff --git a/src/par b/src/par new file mode 100644 index 0000000000000000000000000000000000000000..ffe23201b382ad85b854f2b410f170a9d593b6e4 Binary files /dev/null and b/src/par differ diff --git a/src/parallel.c b/src/parallel.c new file mode 100644 index 0000000000000000000000000000000000000000..4ae1b646b441709643aa91fd5eb71a7eed9de6d2 --- /dev/null +++ b/src/parallel.c @@ -0,0 +1,466 @@ +// serial.c + +#include <stdio.h> +#include <stdlib.h> +#include <mpi.h> + +#define NMAX 100 +#define DATAMAX 1000 +#define DATAMIN -1000 + +/* + * Struct Matrix + * + * Matrix representation consists of matrix data + * and effective dimensions + * */ +typedef struct Matrix { + int mat[NMAX][NMAX]; // Matrix cells + int row_eff; // Matrix effective row + int col_eff; // Matrix effective column +} Matrix; + + +/* + * Procedure init_matrix + * + * Initializing newly allocated matrix + * Setting all data to 0 and effective dimensions according + * to nrow and ncol + * */ +void init_matrix(Matrix *m, int nrow, int ncol) { + m->row_eff = nrow; + m->col_eff = ncol; + + for (int i = 0; i < m->row_eff; i++) { + for (int j = 0; j < m->col_eff; j++) { + m->mat[i][j] = 0; + } + } +} + + +/* + * Function input_matrix + * + * Returns a matrix with values from stdin input + * */ +Matrix input_matrix(int nrow, int ncol) { + Matrix input; + init_matrix(&input, nrow, ncol); + + for (int i = 0; i < nrow; i++) { + for (int j = 0; j < ncol; j++) { + scanf("%d", &input.mat[i][j]); + } + } + + return input; +} + + +/* + * Procedure print_matrix + * + * Print matrix data + * */ +void print_matrix(Matrix *m) { + for (int i = 0; i < m->row_eff; i++) { + for (int j = 0; j < m->col_eff; j++) { + printf("%d ", m->mat[i][j]); + } + printf("\n"); + } +} + + +/* + * Function get_matrix_datarange + * + * Returns the range between maximum and minimum + * element of a matrix + * */ +int get_matrix_datarange(Matrix *m) { + int max = DATAMIN; + int min = DATAMAX; + for (int i = 0; i < m->row_eff; i++) { + for (int j = 0; j < m->col_eff; j++) { + int el = m->mat[i][j]; + if (el > max) max = el; + if (el < min) min = el; + } + } + + return max - min; +} + + +/* + * Function supression_op + * + * Returns the sum of intermediate value of special multiplication + * operation where kernel[0][0] corresponds to target[row][col] + * */ +int supression_op(Matrix *kernel, Matrix *target, int row, int col) { + int intermediate_sum = 0; + for (int i = 0; i < kernel->row_eff; i++) { + for (int j = 0; j < kernel->col_eff; j++) { + intermediate_sum += kernel->mat[i][j] * target->mat[row + i][col + j]; + } + } + + return intermediate_sum; +} + + +/* + * Function convolution + * + * Return the output matrix of convolution operation + * between kernel and target + * */ +Matrix convolution(Matrix *kernel, Matrix *target) { + Matrix out; + int out_row_eff = target->row_eff - kernel->row_eff + 1; + int out_col_eff = target->col_eff - kernel->col_eff + 1; + + // printf("kernel row %d",kernel->row_eff); + // printf("kernel col %d",kernel->col_eff); + + // printf("out_row_eff %d %d",out_row_eff,out_col_eff); + + init_matrix(&out, out_row_eff, out_col_eff); + + for (int i = 0; i < out.row_eff; i++) { + for (int j = 0; j < out.col_eff; j++) { + out.mat[i][j] = supression_op(kernel, target, i, j); + } + } + + return out; +} + + +/* + * Procedure merge_array + * + * Merges two subarrays of n with n[left..mid] and n[mid+1..right] + * to n itself, with n now ordered ascendingly + * */ +void merge_array(int *n, int left, int mid, int right) { + int n_left = mid - left + 1; + int n_right = right - mid; + int iter_left = 0, iter_right = 0, iter_merged = left; + int arr_left[n_left], arr_right[n_right]; + + for (int i = 0; i < n_left; i++) { + arr_left[i] = n[i + left]; + } + + for (int i = 0; i < n_right; i++) { + arr_right[i] = n[i + mid + 1]; + } + + while (iter_left < n_left && iter_right < n_right) { + if (arr_left[iter_left] <= arr_right[iter_right]) { + n[iter_merged] = arr_left[iter_left++]; + } else { + n[iter_merged] = arr_right[iter_right++]; + } + iter_merged++; + } + + while (iter_left < n_left) { + n[iter_merged++] = arr_left[iter_left++]; + } + while (iter_right < n_right) { + n[iter_merged++] = arr_right[iter_right++]; + } +} + + +/* + * Procedure merge_sort + * + * Sorts array n with merge sort algorithm + * */ +void merge_sort(int *n, int left, int right) { + if (left < right) { + int mid = left + (right - left) / 2; + + merge_sort(n, left, mid); + merge_sort(n, mid + 1, right); + + merge_array(n, left, mid, right); + } +} + + +/* + * Procedure print_array + * + * Prints all elements of array n of size to stdout + * */ +void print_array(int *n, int size) { + for (int i = 0; i < size; i++ ) printf("%d ", n[i]); + printf("\n"); +} + + +/* + * Function get_median + * + * Returns median of array n of length + * */ +int get_median(int *n, int length) { + int mid = length / 2; + if (length & 1) return n[mid]; + + return (n[mid - 1] + n[mid]) / 2; +} + + +/* + * Function get_floored_mean + * + * Returns floored mean from an array of integers + * */ +long get_floored_mean(int *n, int length) { + long sum = 0; + for (int i = 0; i < length; i++) { + sum += n[i]; + } + + return sum / length; +} + + +void distribute(void* data, int count, MPI_Datatype datatype, int root, + MPI_Comm communicator) { + int world_rank; + MPI_Comm_rank(communicator, &world_rank); + int world_size; + MPI_Comm_size(communicator, &world_size); + + // Procecss 0 --> Kirim matriks inputan 1,2,3 ke prcess 1,2,3 + // process 1,2,3 -> receive + // prcess 0 --> kirim matriks input 4,5,6, ke process 1,2,3 + + if (world_rank == root) { + // If we are the root process, send our data to every process + int i; + for (i = 0; i < world_size; i++) { + if (i != world_rank) { + MPI_Send(data, count, datatype, i, 0, communicator); + } + } + } else { + // If we are a receiver process, receive the data from the root + MPI_Recv(data, count, datatype, root, 0, communicator, + MPI_STATUS_IGNORE); + + + // Ngitung con sama data range + } +} + +// void init_matrix_kernel() { +// m->row_eff = 2; +// m->col_eff = 2; + +// m->mat[0][0] = 1; +// m->mat[0][1] = 0; +// m->mat[1][0] = 0; +// m->mat[1][1] = -1; +// } + +// main() driver +int main() { + // OPEN MPI + 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); + + const int PING_PONG_LIMIT = 3; + printf("HELLO WORLD\n"); + + // 10 / 4 = 2 2 2 (10-6) + int kernel_row, kernel_col, target_row, target_col, num_targets; + + // reads kernel's row and column and initalize kernel matrix from input + scanf("%d %d", &kernel_row, &kernel_col); + Matrix kernel = input_matrix(kernel_row, kernel_col); + + // reads number of target matrices and their dimensions. + // initialize array of matrices and array of data ranges (int) + scanf("%d %d %d", &num_targets, &target_row, &target_col); + Matrix* arr_mat = (Matrix*)malloc(num_targets * sizeof(Matrix)); + Matrix* arr_mat2 = (Matrix*)malloc(num_targets * sizeof(Matrix)); + int arr_range[num_targets]; + + + // read each target matrix, compute their convolution matrices, and compute their data ranges + for (int i = 0; i < num_targets; i++) { + arr_mat[i] = input_matrix(target_row, target_col); + } + + print_matrix(&kernel); + + int counter_distribute = 0; + int counter_receiver = 0; + + printf("HELLO OPEN MPI\n"); + + + + // --------------------------- Create the datatype ----------------------------- // + MPI_Datatype mat_MPI; + int lengths[3] = { NMAX * NMAX, 1, 1 }; + + // Calculate displacements + // In C, by default padding can be inserted between fields. MPI_Get_address will allow + // to get the address of each struct field and calculate the corresponding displacement + // relative to that struct base address. The displacements thus calculated will therefore + // include padding if any. + MPI_Aint displacements[3]; + Matrix dummy_matrix; + MPI_Aint base_address; + MPI_Get_address(&dummy_matrix, &base_address); + MPI_Get_address(&dummy_matrix.mat, &displacements[0]); + MPI_Get_address(&dummy_matrix.row_eff, &displacements[1]); + MPI_Get_address(&dummy_matrix.col_eff, &displacements[2]); + displacements[0] = MPI_Aint_diff(displacements[0], base_address); + displacements[1] = MPI_Aint_diff(displacements[1], base_address); + displacements[2] = MPI_Aint_diff(displacements[2], base_address); + + MPI_Datatype types[3] = { MPI_INT, MPI_INT, MPI_INT }; + MPI_Type_create_struct(3, lengths, displacements, types, &mat_MPI); + MPI_Type_commit(&mat_MPI); + + // --------------------------- End Create the datatype ----------------------------- // + + // Distribusi matriks input ke process-process + + /* + 0 1 2 3 4 5 6 7 8 9 + + 0 1 2 + + 3 4 5 + + 6 7 8 + + 9 + + */ + + + + + int root = 0; + + if (world_rank == root) { + // If we are the root process, send our data to every process + int i; + for (i = 0; i < world_size; i++) { + if (i != world_rank) { + MPI_Send(&arr_mat[counter_distribute], 1, mat_MPI, i, 0, MPI_COMM_WORLD); + counter_distribute++; + } + } + print_matrix(&kernel); + printf("PRocess 0 distribute\n "); + + } else { + printf("PRocess selain 0 distribute %d \n", world_rank); + // If we are a receiver process, receive the data from the root + Matrix recv_data; + MPI_Recv(&recv_data, 1, mat_MPI, root, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + print_matrix(&recv_data); + + printf("HASILLL\n"); + arr_mat2[counter_receiver] = convolution(&m, &recv_data); + + print_matrix(&arr_mat2[counter_receiver]); + arr_range[counter_receiver] = get_matrix_datarange(&arr_mat2[counter_receiver]); + + counter_receiver++; + } + + while (counter_distribute < PING_PONG_LIMIT){ + // distribute(arr_mat[counter_distribute],1,mat_MPI,0, MPI_COMM_WORLD) + printf("Counter dis %d \n", counter_distribute); + if (world_rank == root) { + // If we are the root process, send our data to every process + int i; + for (i = 0; i < world_size; i++) { + if (i != world_rank) { + MPI_Send(&arr_mat[counter_distribute], 1, mat_MPI, i, 0, MPI_COMM_WORLD); + counter_distribute++; + } + } + print_matrix(&kernel); + printf("PRocess 0 distribute\n "); + + } else { + printf("PRocess selain 0 distribute %d \n", world_rank); + // If we are a receiver process, receive the data from the root + Matrix recv_data; + MPI_Recv(&recv_data, 1, mat_MPI, root, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + print_matrix(&recv_data); + Matrix m; + m.row_eff = 2; + m.col_eff = 2; + + m.mat[0][0] = 1; + m.mat[0][1] = 0; + m.mat[1][0] = 0; + m.mat[1][1] = -1; + print_matrix(&m); + + printf("HASILLL\n"); + arr_mat2[counter_receiver] = convolution(&m, &recv_data); + + print_matrix(&arr_mat2[counter_receiver]); + arr_range[counter_receiver] = get_matrix_datarange(&arr_mat2[counter_receiver]); + + counter_receiver++; + } + } + + MPI_Finalize(); + + + // // Print hasil + // for (int i = 0; i < num_targets; i++) { + // printf("\nMATRIX CONV %d",i); + // print_matrix(arr_mat2); + // } + + // // sort the data range array + // printf("\n"); + // print_array(arr_range,num_targets); + // merge_sort(arr_range, 0, num_targets - 1); + + // int median = get_median(arr_range, num_targets); + // int floored_mean = get_floored_mean(arr_range, num_targets); + + // // print the min, max, median, and floored mean of data range array + // printf("%d\n%d\n%d\n%d\n", + // arr_range[0], + // arr_range[num_targets - 1], + // median, + // floored_mean); + + + + // START OPEN MP + + + + + return 0; +} diff --git a/src/person.c b/src/person.c new file mode 100644 index 0000000000000000000000000000000000000000..3b22c3f717e245676c6098c33f3a64fd623256a3 --- /dev/null +++ b/src/person.c @@ -0,0 +1,150 @@ +/** + * @author RookieHPC + * @brief Original source code at https://www.rookiehpc.com/mpi/docs/mpi_type_create_struct.php + **/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <mpi.h> + +/** + * @brief Illustrates how to create an indexed MPI datatype. + * @details This program is meant to be run with 2 processes: a sender and a + * receiver. These two MPI processes will exchange a message made of a + * structure representing a person. + * + * Structure of a person: + * - age: int + * - height: double + * - name: char[10] + * + * How to represent such a structure with an MPI struct: + * + * +----------------- displacement for + * | block 2: sizeof(int) + sizeof(double) + * | (+ potential padding) + * | | + * +----- displacement for | + * | block 2: sizeof(int) | + * | (+ potential padding) | + * | | | + * displacement for | | + * block 1: 0 | | + * (+ potential padding) | | + * | | | + * V V V + * +------------+------------+------------+ + * | age | height | name | + * +------------+------------+------------+ + * <----------> <----------> <----------> + * block 1 block 2 block 3 + * 1 MPI_INT 1 MPI_DOUBLE 10 MPI_CHAR + **/ + +// struct person_t +// { +// int age; +// double height; +// char name[10]; +// }; + +#define NMAX 100 +#define DATAMAX 1000 +#define DATAMIN -1000 + +typedef struct Matrix { + int mat[NMAX][NMAX]; // Matrix cells + int row_eff; // Matrix effective row + int col_eff; // Matrix effective column +} Matrix; + +void init_matrix(Matrix *m, int nrow, int ncol) { + m->row_eff = nrow; + m->col_eff = ncol; + + for (int i = 0; i < m->row_eff; i++) { + for (int j = 0; j < m->col_eff; j++) { + m->mat[i][j] = 3; + } + } +} + +void print_matrix(Matrix *m) { + for (int i = 0; i < m->row_eff; i++) { + for (int j = 0; j < m->col_eff; j++) { + printf("%d ", m->mat[i][j]); + } + printf("\n"); + } +} + +int main(int argc, char* argv[]) +{ + MPI_Init(&argc, &argv); + + // Get the number of processes and check only 2 processes are used + int size; + MPI_Comm_size(MPI_COMM_WORLD, &size); + if(size != 2) + { + printf("This application is meant to be run with 2 processes.\n"); + MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); + } + + MPI_Datatype mat_MPI; + int lengths[3] = { NMAX * NMAX, 1, 1 }; + + // Calculate displacements + // In C, by default padding can be inserted between fields. MPI_Get_address will allow + // to get the address of each struct field and calculate the corresponding displacement + // relative to that struct base address. The displacements thus calculated will therefore + // include padding if any. + MPI_Aint displacements[3]; + Matrix dummy_matrix; + MPI_Aint base_address; + MPI_Get_address(&dummy_matrix, &base_address); + MPI_Get_address(&dummy_matrix.mat, &displacements[0]); + MPI_Get_address(&dummy_matrix.row_eff, &displacements[1]); + MPI_Get_address(&dummy_matrix.col_eff, &displacements[2]); + displacements[0] = MPI_Aint_diff(displacements[0], base_address); + displacements[1] = MPI_Aint_diff(displacements[1], base_address); + displacements[2] = MPI_Aint_diff(displacements[2], base_address); + + MPI_Datatype types[3] = { MPI_INT, MPI_INT, MPI_INT }; + MPI_Type_create_struct(3, lengths, displacements, types, &mat_MPI); + MPI_Type_commit(&mat_MPI); + + // Get my rank and do the corresponding job + enum rank_roles { SENDER, RECEIVER }; + int my_rank; + MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); + switch(my_rank) + { + case SENDER: + { + // Send the message + Matrix buffer; + + buffer.row_eff = 4; + buffer.col_eff = 4; + init_matrix(&buffer,buffer.row_eff,buffer.col_eff); + printf("MPI process %d sends person:\n\t- ROW = %d\n\t- COL = %d\n\t-\n", my_rank, buffer.row_eff, buffer.row_eff); + MPI_Send(&buffer, 1, mat_MPI, RECEIVER, 0, MPI_COMM_WORLD); + break; + } + case RECEIVER: + { + // Receive the message + Matrix received; + MPI_Recv(&received, 1, mat_MPI, SENDER, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + printf("MPI process %d received person:\n\t- ROW = %d\n\t- COL = %d\n\t-\n", my_rank, received.row_eff, received.row_eff); + print_matrix(&received); + break; + } + } + + MPI_Finalize(); + + return EXIT_SUCCESS; +} diff --git a/src/serial b/src/serial new file mode 100644 index 0000000000000000000000000000000000000000..8405e5cb485403663d575d0118b9b239f66a299e Binary files /dev/null and b/src/serial differ diff --git a/src/serial.c b/src/serial.c index 94b6f1640582724a735f427ae379feea3d2bfbb4..0b574684aec72468c208e79a7ebc45fb5be79017 100644 --- a/src/serial.c +++ b/src/serial.c @@ -237,6 +237,8 @@ int main() { // reads kernel's row and column and initalize kernel matrix from input scanf("%d %d", &kernel_row, &kernel_col); Matrix kernel = input_matrix(kernel_row, kernel_col); + + // reads number of target matrices and their dimensions. // initialize array of matrices and array of data ranges (int) @@ -248,10 +250,23 @@ int main() { for (int i = 0; i < num_targets; i++) { arr_mat[i] = input_matrix(target_row, target_col); arr_mat[i] = convolution(&kernel, &arr_mat[i]); - arr_range[i] = get_matrix_datarange(&arr_mat[i]); + arr_range[i] = get_matrix_datarange(&arr_mat[i]); + + printf("\nhmmmm\n"); + print_matrix(&arr_mat[i]); + } + + // Print hasil + for (int i = 0; i < num_targets; i++) { + printf("\nMATRIX CONV %d",i); + printf("\nArray mat\n"); + print_matrix(&arr_mat[i]); } + // sort the data range array + printf("\n"); + print_array(arr_range,num_targets); merge_sort(arr_range, 0, num_targets - 1); int median = get_median(arr_range, num_targets);