Untitled

mail@pastecode.io avatar
unknown
plain_text
2 years ago
4.2 kB
3
Indexable
Never
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <string.h>
#include <math.h>
#include <omp.h>

char *help = "\n\
   ** Matrix_Mult_OpenMP.c ** \n\
   Inmultirea matricelor in OpenMP \n\
   \n\
   Se compileaza: \n\
   gcc Matrix_Mult_OpenMP.c -o Matrix_Mult_OpenMP  -fopenmp -lgomp  \n\
   \n\
   Se lanseaza cu parametrii n, p, mod, max_rep \n\
   Implicit n = 1024, p = 1, mod = 0, max_rep = 1 \n\
   \n\
   ./Matrix_Mult_OpenMP n p mod max_rep \n\
   \n\
   Parametrul mod este optional - implicit este 0: \n\
 	mod 0: Inmultire paralela cu partitionare pe linii \n\
	mod 1: Inmultire paralela cu partitionare pe linii întretesute \n\
	mod 2: Inmultire paralela cu partitionare pe coloane cu interschimb cu 1 regiune paralela \n\
	mod 3: Inmultire paralela cu partitionare pe coloane cu n regiuni paralele \n\
	mod 4: Inmultire paralela cu partitionare pe coloane cu 1 regiune paralela \n\
	mod 5: Inmultire paralela cu partitionare pe blocuri cu 1 regiune paralela \n\
   \n\
   Se executa de max_rep ori si se mediaza timpul de executie dat in secunde \n\
   care se afiseaza si se inscrie in fisierul Res_Matrix_Mult_OpenMP.txt \n";

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

  int n = 1024;    // Dimensiune matrice
  int p = 1;       // Numar thread-uri
  int mod = 0;     // Mod 0: partitionare pe linii
  int max_rep = 1; // Numar de repetari ale executiei

  float **a, *c; // Matricele de date
  int i, j, k, t, f, d, rep;
  char *text_mod;

  struct timeval t1, t2;
  float tp;
  char *fn = "Res_Matrix_Mult_OpenMP.txt";
  FILE *fp;

  // Citire parametri
  if (argc >= 2 && strcmp(argv[1], "-help") == 0)
  {
    printf("%s\n", help);
    return 0;
  }
  if (argc >= 2)
    n = atoi(argv[1]);
  if (argc >= 3)
    p = atoi(argv[2]);
  if (argc >= 4)
    mod = atoi(argv[3]);
  if (argc >= 5)
    max_rep = atoi(argv[4]);

  // Testare parametri
  if (n < 2)
  {
    printf("Eroare: n < 2 \n");
    exit(0);
  }
  if (p < 1)
  {
    printf("Eroare: p < 1 \n");
    exit(0);
  }
  if (max_rep < 1)
  {
    printf("Eroare: max_rep < 1 \n");
    exit(0);
  }
  // La partitionare in blocuri: p patrat perfect, n divizibil cu sqrt(p)
  if (mod == 5)
  {
    if (sqrt(p) != (int)sqrt(p))
    {
      printf("Eroare: partitionare in blocuri (mod = %d) si p nu este patrat perfect\n", mod);
      exit(0);
    }
    if (n % (int)sqrt(p) != 0)
    {
      printf("Eroare: partitionare in blocuri (mod = %d) si n nu este divizibil cu sqrt(p)\n", mod);
      exit(0);
    }
  }
  f = sqrt(p);
  d = n / f;

  // Alocarea datelor
  a = (float **)malloc(sizeof(float *) * n);
  c = (float *)malloc(sizeof(float) * n);

  for (i = 0; i < n; i++)
  {
    a[i] = (float *)malloc(sizeof(float) * n);
  }
  // Initializare matrice a, b
  for (i = 0; i < n; i++)
    for (j = 0; j < n; j++)
    {
      a[i][j] = 1;
    }

  gettimeofday(&t1, NULL);

  for (rep = 0; rep < max_rep; rep++)
  {

    if (p == 1)
    {
      // Inmultirea secventiala a doua matrice
      text_mod = "Inmultire secventiala";
      for (i = 0; i < n; i++)
      {
        c[i] = 0;
        for (j = 0; j < n; j++)
          c[i] += a[i][j];
      }
    }
    // Inmultirea paralela a doua matrice
    else if (mod == 0)
    {
      text_mod = "mod 0: Inmultire paralela cu partitionare pe linii cu 1 regiune paralela";
#pragma omp parallel num_threads(p) shared(a, c, n) private(i, j)
      {
#pragma omp for
        for (i = 0; i < n; i++)
        {
          c[i] = 0;
          for (j = 0; j < n; j++)
            c[i] += a[i][j];
        }
      }
    }
  }
  gettimeofday(&t2, NULL);
  tp = ((float)(t2.tv_sec - t1.tv_sec) + 0.000001 * (t2.tv_usec - t1.tv_usec)) / max_rep;

  // Scriere timp de executie in fisier
  fp = fopen(fn, "a");
  if (p == 1)
    fprintf(fp, "\n%f  ", tp);
  else
    fprintf(fp, "%f  ", tp);
  fclose(fp);

  // Afisare timp executie mediat pe max_rep teste repetate
  printf("%s \n", text_mod);
  printf("%d rep, n = %d, p = %d, t = %f sec\n", max_rep, n, p, tp);

  // Afisare rezultate
  if (n <= 16)
  {
    for (i = 0; i < n; i++)
    {
      for (j = 0; j < n; j++)
        printf("%4.0f  ", c[i]);
      printf("\n");
    }
  }

  return 0;
}