Untitled
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*)¶ms[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; }