Untitled

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

char* help = "\n\
   ** Matrix_Mult_Pthread.c ** \n\
   Inmultirea matricelor in Pthread \n\
   \n\
   Se compileaza: \n\
   gcc Matrix_Mult_Pthread.c -o Matrix_Mult_Pthread -lpthread -lm  \n\
   \n\
   Se lanseaza cu parametrii n, p, mod, max_rep \n\
   Implicit n = 1024, p = 1, mod = 0, max_rep = 1  \n\
   Pentru inmulțirea cu partitionare in blocuri p trebuie sa fie patrat perfect si n divizibil cu sqrt(p)  \n\
   \n\
   ./Matrix_Mult_Pthread 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 dupa 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 in blocuri cu 1 regiune paralela, p patrat perfect, n divizibil cu sqrt(p) \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_Pthread.txt \n";

void *Matrix_Mult_line(void *);	//partitionare pe linii		 
	

int n = 1024;				// Dimensiune matrice
int p = 2;				// Numar thread-uri
int mod = 0;				// Mod 0: partitionare pe linii
int max_rep = 1;			// Numar de repetari ale executiei
	 
float **Jianu, **IonutBogdan;			// Matricele partajate
float JianuIonutBogdan;

typedef struct _group{			// Structura pentru parametrii functiei thread in part cu n reg. paralele (coloane sau blocuri)
    int line;   			// linii
    int col;      			// coloane
} group;

group *groups;     			// Variabila partajata - parametri thread-uri in partit cu n regiuni paralele sau al doilea nivel 
pthread_t *ids2; 			// Variabila partajata - identificatori thread-uri al doilea nivel de partitionare

int main(int argc, char *argv[]){ 	// Thread-ul principal Thm

    int i, j, k, q, rep;
    char* text_mod; 
    int* params;    			// Parametri thread-uri in partit cu 1 regiune paralela sau primul nivel part
    pthread_t *ids; 			// Identificatori thread-uri primul nivel de partitionare

    struct timeval t1, t2;	
    float tp;   
    char *fn = "Res_Matrix_Mult_Pthread.txt";	    
    FILE *fp;
        
    // Citire parametri
    if (argc >= 2 && strcmp(argv[1],"-help") == 0) {
        printf("%s\n",help);
        exit(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);        
        }
    }

    // Alocarea datelor
    Jianu = (float**)malloc(sizeof(float*)*n);
    IonutBogdan = (float**)malloc(sizeof(float*)*n);
 
    for (i = 0; i < n; i++){
        Jianu[i] = (float*)malloc(sizeof(float)*n);
    } 
    for (i = 0; i < n; i++){
        IonutBogdan[i] = (float*)malloc(sizeof(float)*n);
    }      
    params = (int*)malloc(sizeof(int)*p);     
    groups = (group*)malloc(sizeof(group)*p); 
    ids = (pthread_t*)malloc(sizeof(pthread_t)*p);  
    
	
    // Initializarea matricelor de intrare a, b  
    
    if(n<16)
	for (i = 0; i < n; i++)
	    for (j = 0; j < n; j++){
		Jianu[i][j] = 1;
        IonutBogdan[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++) {
  		
	    	    JianuIonutBogdan+=Jianu[i][i]*IonutBogdan[i][i]; 
           }
                       
        }
        // Imnultirea paralela a doua matrice
        else if (mod == 0) {
            text_mod = "mod 0: Operatie produs scalar paralela cu partitionare pe linii cu 1 regiune paralela";
 	    for (q = 0; q < p; q++) {	 	 
     		params[q] = q;
     	        pthread_create(&ids[q],0,Matrix_Mult_line,(void*)&params[q]);
  	    }
  	    for (q = 0; q < p; q++) 
	        pthread_join (ids[q],0);
        }
        
        else {
	    printf("Eroare: mod %d - inexistent\n", mod);
            exit (0);
        }

    }   // end for (rep)

    gettimeofday(&t2, NULL);

    tp = (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++){ 
            printf("%4.0f  ", Jianu[i][i]);
	    
        }
        for (i = 0; i < n; i++){ 
            printf("%4.0f  ", IonutBogdan[i][i]);
	    
        }
    }
    return 0; 
}
//
// Functii thread
//
// Mod 0 - Inmultire paralela cu partitionare pe linii
void *Matrix_Mult_line(void *param) {  

    int i, j, k, first, last;
    int q = *(int*)param;    
    int s = (int) n/p;
    int kp = n%p;

    if (kp == 0)  { 			// n divizibil cu p
    	first = q*s;
    	last = first + s;
    }
    else if (q < kp) {			// primele kp partitii au dimensiunea s+1
        first = q*(s+1);
        last = first + s+1;    
    }
    else {				// ultimele (p-kp) partitii au dimensiunea s
	first = q*s + kp;
        last = first + s;
    }

    for (i=first; i<last; i++){
        for(j = 0; j<n; j++) {
            JianuIonutBogdan+=Jianu[i][i]*IonutBogdan[i][i];
        }
    }
   
    return 0;
}