#include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <mpi.h> #include "vec.h" int main (int argc, char* argv[]) { MPI_Init (&argc, &argv); // MPI_COMM_WORLD is the default communicator that contains all ranks int rank, size; MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); char node_name[MPI_MAX_PROCESSOR_NAME]; int node_name_len; MPI_Get_processor_name(node_name,&node_name_len); // make sure we are not running on a login node! if ((strcmp(node_name,"tinkercliffs1") == 0) || (strcmp(node_name,"tinkercliffs2") == 0)) { printf ("error : running on login node %s!\n",node_name); return 1; } // read the filename from the command line if (argc < 4) { printf ("command usage: %s %s %s %s\n",argv[0],"filename","num_pairs","seed"); return 1; } char* filename = argv[1]; int num_pairs = atoi(argv[2]); // seed the random number generator using command line seed srandom(atoi(argv[3])); // open the text file for reading FILE* fptr; fptr = fopen(filename,"r"); // need to check for null if (fptr == 0) { printf ("Error opening data file %s.\n",filename); exit(1); } // read the number of points and the dimension of each point int num_points, dim; if (fscanf(fptr,"%*c %d %d",&num_points, &dim) != 2) { printf ("error reading the number of points and the dimension\n"); return 1; } // Read vectors from stdin and store them in a 2d array double* data = (double*)malloc(num_points*dim*sizeof(double)); if (data == NULL) { printf ("malloc return NULL pointer!\n"); return 1; } for (int i=0;i<num_points;i++) { if (vec_read_file(fptr,data+i*dim,dim) != dim) { printf ("error reading the next point from the file %s\n",filename); return 1; } } // close the data file fclose(fptr); // start the timer double start_time, end_time; start_time = MPI_Wtime(); // find the approximate extreme pair double max_dist_sq = 0; int pairs_checked = 0; int extreme[2]; for (int p=0;p<num_pairs;p++) { int i = random() % num_points; int j = random() % num_points; double dist_sq = vec_dist_sq(data+i*dim,data+j*dim,dim); pairs_checked += 1; if (dist_sq > max_dist_sq) { max_dist_sq = dist_sq; extreme[0] = i; extreme[1] = j; } } // all nonzero ranks send their approximate extreme pair to rank 0 if (rank == 0) { MPI_Status status; int rank_extreme[2]; int rank_pairs_checked; for (int src=1;src<size;src++) { MPI_Recv(&rank_pairs_checked,1,MPI_INT,src,0,MPI_COMM_WORLD,&status); pairs_checked += rank_pairs_checked; MPI_Recv(rank_extreme,2,MPI_INT,src,0,MPI_COMM_WORLD,&status); int i = rank_extreme[0]; int j = rank_extreme[1]; double dist_sq = vec_dist_sq(data+i*dim,data+j*dim,dim); if (dist_sq > max_dist_sq) { max_dist_sq = dist_sq; extreme[0] = rank_extreme[0]; extreme[1] = rank_extreme[1]; } } } else { int dest = 0; MPI_Send(&pairs_checked,1,MPI_INT,dest,0,MPI_COMM_WORLD); MPI_Send(extreme,2,MPI_INT,dest,0,MPI_COMM_WORLD); } // stop the timer end_time = MPI_Wtime(); // output the results if (rank == 0) { printf ("elapsed time = %.4f seconds\n",end_time-start_time); printf ("pairs checked = %d\n",pairs_checked); printf ("Approximate Extreme Distance = %.2f\n",sqrt(max_dist_sq)); printf ("Approximate Extreme Pair = %d %d\n",extreme[0],extreme[1]); } // free memory allocated for dataset free(data); MPI_Finalize(); }