Medians and multiples. MPI version

We consider a matrix nxn of integers. The medians of each row are obtained, and for each median, the number of its multiples in all the matrix is obtained. For a median with value 0 the value is 0. The solution should use MPI.


A number of problems is solved. For each problem the function to parallelize has:

Input parameters:

-int n: the size of the matrix, nxn

-int *m: the matrix

Output parameter:

-int *v: the vector of solutions, of size

Parallelism parameters:

-int np: number of MPI processes

-int node: process identifier


Files

3

10 1 -1000 1000

1020 4 -994 994

1010 3 -500 499

/*

CPP_CONTEST=2017ClaA

CPP_PROBLEM=F

CPP_LANG=CPP+MPI

CPP_PROCESSES_PER_NODE=1

CPP_NUM_NODES=1

*/

//for the number of MPI processes in marte and mercurio:

//CPP_PROCESSES_PER_NODE=marte num_pro_marte mercurio num_pro_mercurio

#include <stdlib.h>

#include <stdio.h>

#include <omp.h>

#include <iostream>

#include <iomanip>

#include <math.h>

using namespace std;

int elementinposition(int *a,int izq,int der,int pos)

{

int i,j,t;

int piv=a[izq];

i=izq+1;

j=der;

while(i<=j)

{

while(i<=der && a[i]<=piv)

{

i++;

}

while(j>izq && a[j]>piv)

{

j--;

}

if(i<j)

{

t=a[i];

a[i]=a[j];

a[j]=t;

}

}

a[izq]=a[j];

a[j]=piv;

if(j==pos)

{

return a[j];

}

else if(j>pos)

{

return elementinposition(a,izq,j-1,pos);

}

else if(j>=izq && j<pos)

{

return elementinposition(a,j+1,der,pos);

}

}

void sec(int n,int *m,int *v,int np,int node)

{

int *med=new int[n]; //vector of medians

//Obtain the median of each row

for(int i=0;i<n;i++)

{

med[i]=elementinposition(&m[i*n],0,n-1,n/2);

}

//Obtain multiples of the medians

for(int i=0;i<n;i++)

{

int data=med[i];

v[i]=0;

if(data!=0 and data!=1 and data!=-1)

{

for(int j=0;j<n;j++)

{

for(int k=0;k<n;k++)

{

if(m[j*n+k]%data==0)

v[i]++;

}

}

}

else if(data==1 or data==-1)

v[i]=n*n;

}

delete[] med;

}

#include <stdlib.h>

#include <stdio.h>

#include <sys/time.h>

#include <mpi.h>

#include <signal.h>

#include <unistd.h>

#include <iostream>

#include <iomanip>

using namespace std;

// Scheme for the problem of Medians and multiples - OpenMP version

// First classification contest for the Spanish Parallel Programming Contest 2017, problem F

//initialize a vector to a constant value

void inicializematrix(int n,int *m,int lv,int uv)

{

for(int i=0;i<n;i++)

m[i]=(int) (((1.*rand())/RAND_MAX)*(uv-lv)+lv);

}

//output to be compared with the output of the solution provided by the organization

void escribirvector(int n,int *v)

{

for(int i=0;i<n;i++)

{

cout <<v[i]<<" ";

}

cout <<endl;

}

/*

c

c mseconds - returns elapsed milliseconds since Jan 1st, 1970.

c

*/

long long mseconds(){

struct timeval t;

gettimeofday(&t, NULL);

return t.tv_sec*1000 + t.tv_usec/1000;

}

//abort with the maximum execution time is reached

static void alarm_handler(int sig) {

fprintf(stderr, "Time Limit Exceeded\n");

abort();

}

//the external function to be parallelized by the contestants

extern void sec(int,int *,int *,int,int);

int main(int argc,char *argv[]) {

int num_problems; //number of problems

int n; //size of the matrix

int *m; //matrix

int *v; //solution vector

int seed; //seed for random generation

int lower_value; //lower bound for the values in the vector

int upper_value; //upper bound for the values in the vector

long long ti,tf,tt=0; //initial, final and total times

int np,node; //number of processes and process identifier

FILE *stats_file = fopen("stats", "w");

//to stablish a time limit

struct sigaction sact;

sigemptyset(&sact.sa_mask);

sact.sa_flags = 0;

sact.sa_handler = alarm_handler;

sigaction(SIGALRM, &sact, NULL);

alarm(40); /* time limit */

MPI_Init(&argc,&argv);

MPI_Comm_size(MPI_COMM_WORLD,&np);

MPI_Comm_rank(MPI_COMM_WORLD,&node);

// The number of test cases is read

// and sent to all the processes

if(node==0)

{

cin >> num_problems;

MPI_Bcast(&num_problems,1,MPI_INT,0,MPI_COMM_WORLD);

}

else

{

MPI_Bcast(&num_problems,1,MPI_INT,0,MPI_COMM_WORLD);

}

for(int i=0;i<num_problems;i++)

{

if(node==0)

{

cin >>n; // The first argument is the size of the matrix

cin >>seed; //seed for the random generation of data

cin >>lower_value; //lower bound for the values in the matrix

cin >>upper_value; //upper bound for the values in the matrix

// Space for the data

m=new int[n*n];

v = new int[n];

srand(seed);

inicializematrix(n*n,m,lower_value,upper_value);

}

MPI_Barrier(MPI_COMM_WORLD);

ti=mseconds();

sec(n,m,v,np,node);

MPI_Barrier(MPI_COMM_WORLD);

tf=mseconds();

if(node==0)

{

// The time of the first input is not considered

if(i!=0) tt+=tf-ti;

// The results of each problem are written,

// even for the first problem

escribirvector(n,v);

delete[] v;

delete[] m;

}

}

if(node==0)

{

fprintf(stats_file, "%Ld\n", tt);

fclose(stats_file);

}

MPI_Finalize();

return 0;

}