Created
April 20, 2022 10:20
-
-
Save panta/065699943ba0e8975544e41288a9a1eb to your computer and use it in GitHub Desktop.
ITS Meccatronico - Soluzione esercizio 3 lezione 6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <pthread.h> | |
#include <time.h> | |
// Data la definizione di prodotto scalare | |
// tra vettori enunciata qui sopra, | |
// scrivere un programma single-threaded | |
// che calcoli il prodotto scalare tra | |
// due vettori di double di grande | |
// dimensione (es. 10k elementi). | |
// Scrivere una versione del programma | |
// multi-threaded con NUM_THREADS | |
// threads che divida il lavoro tra | |
// i vari thread. Verificare che i | |
// risultati siano identici alla | |
// versione single-threaded. | |
// Confrontare le performance con la | |
// versione single-threaded. | |
#define NUM_THREADS 4 | |
double dot(double u[], double v[], int size) { | |
double r = 0.0; | |
for (int i = 0; i < size; i++) | |
r += u[i] * v[i]; | |
return r; | |
} | |
void fillrand(double u[], int size) { | |
for (int i = 0; i < size; i++) { | |
u[i] = ((double)rand() / (double)RAND_MAX); | |
} | |
} | |
void printvec(double u[], int size) { | |
printf("["); | |
for (int i = 0; i < size; i++) { | |
printf("%g", u[i]); | |
if (i + 1 < size) | |
printf(", "); | |
} | |
printf("]\n"); | |
} | |
struct subvecs { | |
double *u; | |
double *v; | |
double r; | |
int size; | |
}; | |
void *threadfunc(void *param) { | |
struct subvecs *work = (struct subvecs *)param; | |
work->r = dot(work->u, work->v, work->size); | |
return NULL; | |
} | |
double mt_dot(double u[], double v[], int size) { | |
int size_per_thread = size / NUM_THREADS; | |
pthread_t tid[NUM_THREADS]; | |
struct subvecs work[NUM_THREADS]; | |
for (int i = 0; i < NUM_THREADS; i++) { | |
work[i].u = &u[i * size_per_thread]; | |
work[i].v = &v[i * size_per_thread]; | |
work[i].size = size_per_thread; | |
if (pthread_create(&tid[i], NULL, threadfunc, &work[i]) != 0) { | |
perror("pthread_create"); | |
exit(EXIT_FAILURE); | |
} | |
} | |
double r = 0.0; | |
for (int i = 0; i < NUM_THREADS; i++) { | |
pthread_join(tid[i], NULL); | |
r += work[i].r; | |
} | |
return r; | |
} | |
#define BIGVECSIZE 800000 | |
double g_u[BIGVECSIZE]; | |
double g_v[BIGVECSIZE]; | |
int main() { | |
fillrand(g_u, BIGVECSIZE); | |
fillrand(g_v, BIGVECSIZE); | |
// printf("u = "); printvec(g_u, BIGVECSIZE); | |
// printf("v = "); printvec(g_v, BIGVECSIZE); | |
time_t t1 = time(NULL); | |
double r; | |
for (int i = 0; i < 500; i++) | |
r = dot(g_u, g_v, BIGVECSIZE); | |
time_t t2 = time(NULL); | |
printf("[S] u . v = %g (%lds)\n", r, (long)(t2-t1)); | |
time_t t3 = time(NULL); | |
double r2; | |
for (int i = 0; i < 500; i++) | |
r2 = mt_dot(g_u, g_v, BIGVECSIZE); | |
time_t t4 = time(NULL); | |
printf("[T] u . v = %g (%lds)\n", r2, (long)(t4-t3)); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment