Untitled

 avatar
unknown
plain_text
3 years ago
4.1 kB
9
Indexable
#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*)&params[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;
}