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
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;
}
esquema-mpi.cpp (non modifiable, used by mooshak for in/out and evaluation, provided for local experimentation)
#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;
}