#include <stdio.h> #include <stdlib.h> #include <mpi.h> #include <unistd.h> #include <time.h> #include "fuzzykmeans.h" #include "oracle.h" /* Uncomment for Debugging Print Statments */ // #define DEBUG static void find_min_and_max(double arr[], double min_and_max[], int len); int main(int argc, char **argv) { int rank, size, n, k, r; double min_max[4], g_max_x = 0, g_max_y = 0, g_min_x = 0, g_min_y = 0; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); // Total number of data points n = atoi(argv[1]); // Total number of clusters k = atoi(argv[2]); // Display runtime or data and clusters r = atoi(argv[3]); // Gets start time for runtime option double start = (r) ? -1 : MPI_Wtime(); // Increases number of points until all ranks // possess an equal number of data points while (n % size != 0) n++; // Number of data points per rank int num_points = n / size; // Rank data and global cluster center arrays double data[2 * num_points], centers[2 * k]; // Generates an equal number of data points for each rank oracle(data, rank * num_points, num_points); if (r) // Prints data points in ascending rank order { int rec[1], print[1]; // Receives message from previous rank to print if (rank != 0) MPI_Recv(rec, 1, MPI_INT, rank - 1, 999, MPI_COMM_WORLD, MPI_STATUS_IGNORE); // Each rank prints its own data points for (int x = 0; x < 2 * num_points; x += 2) printf("Rank %d DP: %lf, %lf\n", rank, data[x], data[x + 1]); // Sends message to next rank to print if (rank != (size - 1)) MPI_Send(print, 1, MPI_INT, rank + 1, 999, MPI_COMM_WORLD); } // Finds the minimum and maximum x and y values find_min_and_max(data, min_max, num_points); // Sets global minimum and maximum x and y values for all ranks MPI_Allreduce(&min_max[0], &g_max_x, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); MPI_Allreduce(&min_max[1], &g_max_y, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); MPI_Allreduce(&min_max[2], &g_min_x, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD); MPI_Allreduce(&min_max[3], &g_min_y, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD); #ifdef DEBUG printf("X_MAX for Rank %d: %lf\n", rank, g_max_x); printf("Y_MAX for Rank %d: %lf\n", rank, g_max_y); printf("X_MIN for Rank %d: %lf\n", rank, g_min_x); printf("Y_MIN for Rank %d: %lf\n", rank, g_min_y); #endif // Rank 0 creates the initial cluster centers // for all ranks to use in fuzzykmeans if (rank == 0) { struct drand48_data seed; srand48_r(time(NULL), &seed); // Sets ranges for x and y values double x_range = g_max_x - g_min_x, y_range = g_max_y - g_min_y, rand_x, rand_y; // Randomly generates cluster centers within the // ranges defined above for (int i = 0; i < 2 * k; i += 2) { // Generates random double between 0 and 1 drand48_r(&seed, &rand_x); drand48_r(&seed, &rand_y); centers[i] = rand_x * x_range; centers[i + 1] = rand_y * y_range; } } // Rank zero sends initial clusters centers to other ranks while // non-zero ranks receive cluster centers from rank zero MPI_Bcast(centers, 2 * k, MPI_DOUBLE, 0, MPI_COMM_WORLD); #ifdef DEBUG for (int i = 0; i < 2 * k; i++) printf("Center %d for Rank %d : %lf\n", i, rank, centers[i]); #endif // fuzzykmeans calculation fuzzykmeans(data, num_points, centers, k); // Rank 0 prints the final cluster centers if (r && rank == 0) for (int x = 0; x < 2 * k; x += 2) printf("Center: %lf, %lf\n", centers[x], centers[x + 1]); // Hghest rank prints the runtime of the program // given the valid runtime option else if (!r && (rank == (size - 1))) printf("Runtime: %lf\n", MPI_Wtime() - start); MPI_Finalize(); return 0; } /* Finds the minimum and maximum x and y values for an array of lenght 2 * len */ static void find_min_and_max(double arr[], double min_and_max[], int len) { // Sets main and max x and y to first values in arr min_and_max[0] = arr[0]; // -- MAX X min_and_max[1] = arr[1]; // -- MAX Y min_and_max[2] = arr[0]; // -- MIN X min_and_max[3] = arr[1]; // -- MIN Y for (int i = 0; i < 2 * len; i += 2) { double x_coor = arr[i], y_coor = arr[i + 1]; if (x_coor > min_and_max[0]) min_and_max[0] = x_coor; else if (x_coor < min_and_max[2]) min_and_max[2] = x_coor; if (y_coor > min_and_max[1]) min_and_max[1] = y_coor; else if (y_coor < min_and_max[3]) min_and_max[3] = y_coor; } }