Untitled
unknown
plain_text
2 years ago
4.1 kB
7
Indexable
Never
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #include <sys/time.h> char* help = "\n\ ** Reduction_Pthread.c ** \n\ Adunarea vectorilor in Pthread \n\ \n\ Se compileaza: \n\ gcc Reduction_Pthread.c -o Reduction_Pthread -lpthread \n\ \n\ Se lanseaza cu parametrii n, p, max_rep (implicit n = 1024, p = 1, max_rep = 1) \n\ \n\ ./Reduction_Pthread n p max_rep \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_Reduction_Pthread.txt \n"; int n = 1024; // Variabila partajata dimensiune matrice int p = 1; // Variabila partajata numar thread-uri float *a, *b; // Vectorul partajat double sum; pthread_mutex_t mutex; void * Reduction(void *param); int main(int argc, char *argv[]){ int i, q, rep; int max_rep = 1; // Numar maxim de repetari ale executiei int* params; // Parametri thread-uri pthread_t *ids; // Identificatori thread-uri struct timeval t1, t2; float tp; char *fn = "Res_Reduction_Pthread.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) max_rep = atoi(argv[3]); // 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); } // Alocarea datelor a = (float*)malloc(sizeof(float)*n); b= (float*)malloc(sizeof(float)*n); params = (int*)malloc(sizeof(int)*p); ids = (pthread_t*)malloc(sizeof(pthread_t)*p); pthread_mutex_init(&mutex,0); // Initializare mutex // Initializarea vectorului de intrare if (n <= 16) for (i = 0; i < n; i++) { a[i] = 1; b[i]=1; } else for (i = 0; i < n; i++) a[i] = rand()/(float)RAND_MAX; gettimeofday(&t1, NULL); for (rep = 0; rep < max_rep; rep++) { sum = 0.0; if (p == 1) { // Reducerea secventiala for (i = 0; i < n; i++) sum += a[i]*b[i]; } else { // Reducerea paralela for (q = 0; q < p; q++) { // creare thread-uri de lucru params[q] = q; pthread_create(&ids[q],0,Reduction,(void*)¶ms[q]); } for (q = 0; q < p; q++) pthread_join (ids[q],0); } } // end for (rep) 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 printf("%d rep, sum = %f, n = %d, p = %d, t = %f sec\n", max_rep, sum, n, p, tp); return 0; } // // Functie thread // void *Reduction (void *param) { double psum = 0; int i, first, last; int q = *(int*)param; int s = (int) n/p; int k = n%p; if (k == 0) { // n divizibil cu p first = q*s; last = first + s; } else if (q < k) { // primele k partitii au dimensiunea s+1 first = q*(s+1); last = first + s+1; } else { // ultimele (p-k) partitii au dimensiunea s first = q*s + k; last = first + s; } // Etapa 1 - reducerea partiala (in partitie) for(i = first; i < last; i++) psum += a[i]*b[i]; // Etapa 2: - reducere globala folosind un mutex pthread_mutex_lock(&mutex); sum += psum; pthread_mutex_unlock(&mutex); return 0; }