Maximum coincidence with a mask in 2D. MPI version.

In a bidimensional array of characters A of size NxN, we want to find the maximum number of coincidences with a bidimensional mask B of size MxM.


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

Input parameters:

-int N: for the size of the array

-char *A: the array where to search for the maximum

-int M: for the size of the mask

-char *B: the mask

-int node: node identifier

int np: number of MPI processes

return an integer with the maximum number of coincidences


Files

3
13 4 2 3
1800 48 6 5
1950 41 9 7
/*
  CPP_CONTEST=2017
  CPP_PROBLEM=F
  CPP_LANG=CPP+MPI
  CPP_PROCESSES_PER_NODE=1
  CPP_NUM_NODES=1
*/

#include <stdlib.h>
#include <mpi.h>

int count(int ld,int n,char *a,char *b)
{
  int i,j;
  int value=0;
  for(i=0;i < n;i++)
    for(j=0;j < n;j++)
      if(a[i*ld+j]==b[i*n+j])
        value++;
  return value;
}

int  sec(int n,char *a,int m,char *b,int node,int np)
{
  int i, j;
  int maximum=0,value;

  for (i = 0; i <= n-m; i++)
  {
      for (j = 0; j <= n-m; j++)
      { 
          value=count(n,m,&a[i*n+j],b);
          if(value>maximum)
            maximum=value;
      }
  }
  return maximum;
}
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <mpi.h>
#include <signal.h>
#include <unistd.h>

//Spanish Parallel programming Contest 2017. Problem F - CESGA 
//Maximum coincidence with a mask in 2D. MPI version.
//Schema for In/Out, validation and execution time

void generar(char *m, int t,int sup) {
  int i;

  for (i = 0; i < t; i++) {
      m[i] = (char) (((1. * rand()) / RAND_MAX)*sup)+'a';
  }
}

void escribir(char *m, int t) {
  int i;

  for (i = 0; i < t; i++) {
      printf("%c ", m[i]);
  }
  printf("\n");
}

/*
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;
}

static void alarm_handler(int sig) {
  fprintf(stderr, "Time Limit Exceeded\n");
  abort();
}

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

int main(int argc,char *argv[]) {
  int N,M,cuantos,result;
  bool correcto=true;
  int semilla,upper;
  char *A,*B;
  long long ti,tf,tt=0;
  int nodo,np;

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

  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,&nodo);
 
// The number of test cases is read
// and sent to all the processes
  if(nodo==0)
  {
    scanf("%d",&cuantos);
    MPI_Bcast(&cuantos,1,MPI_INT,0,MPI_COMM_WORLD);
  }
  else
  {
    MPI_Bcast(&cuantos,1,MPI_INT,0,MPI_COMM_WORLD);
  }

  for(int i=0;i<cuantos;i++)
  {
    if(nodo==0)
    {
      scanf("%d",&N);                   // Matrices size
      scanf("%d",&M);                   // mask size
      scanf("%d",&semilla);             // seed for random generation
      scanf("%d",&upper);                 // upper value for random generation

// Space for the matrix, the values, rows and columns
      A = (char *) malloc(sizeof(double)*N*N);
      B = (char *) malloc(sizeof(double)*M*M);

      srand(semilla);
     
      generar(A,N*N,upper);
      generar(B,M*M,upper);
/*#ifdef DEBUG
    escribir(A,N*N);
    escribir(B,M*M);
#endif*/
   }
    MPI_Barrier(MPI_COMM_WORLD);
    ti=mseconds(); 
    result=sec(N,A,M,B,nodo,np);
   MPI_Barrier(MPI_COMM_WORLD);
    tf=mseconds(); 
    if(nodo==0)
    {
      if(i!=0) tt+=tf-ti;
      printf("%d\n",result);
      free(A);
      free(B);
    }
  }
  if(nodo==0)
  {   
     fprintf(stats_file, "%Ld\n", tt);
     fclose(stats_file);
  }
  MPI_Finalize();
  return 0;
}