Skip to content
Snippets Groups Projects
mpi_extreme_approx.c 3.63 KiB
Newer Older
Jason R Wilson's avatar
Jason R Wilson committed
#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();
}