cours_prog_systeme/TP/TP3/calcul.c
2021-08-22 13:28:10 +02:00

174 lines
No EOL
4.1 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <pthread.h>
#include <unistd.h>
#define D 1000
/*
* TP 3
* 1) Fait et ok.
* 2) Fait et ok. On constate que la seconde méthode est plus longue.
* 3) Ça ne donne pas la bonne valeur : il faut proteger l'incrémentation par un mutex
* 4) On constate que le temps de'exécution augmente de manière exp.
*/
int V[D];
int V_plus[D];
int A[D][D];
int t_num = 0;
int compt_glob = 0;
void err_args() {
printf("[~] Usage: calcul [-m [1|2]] [-t #] [-i ##]\n");
printf("Aide :\n -i [ITÉRATIONS]\n -m [MÉTHODE]\n -t [THREAD] (max: 16)\n -v, verbose output\n");
exit(-1);
}
void * fn_thread_m1 (void * p_int) {
int nb_t = *(int *) p_int;
int lt = (D / nb_t) + 1;
int num = t_num;
++t_num;
for (int i = num * lt; i < (num+1)*lt && i < D; ++i){
for (int j = 0; j < D; ++j){
V_plus[i] += V[j] * A[i][j];
//compt_glob++;
}
}
pthread_exit(0);
}
void * fn_thread_m2 (void * p_int) {
int nb_t = *(int *) p_int;
int lt = (D / nb_t) + 1;
int num = t_num;
++t_num;
for (int j = 0; j < D; ++j){
for (int i = num * lt; i < (num+1)*lt && i < D; ++i){
V_plus[i] += A[i][j] * V[j];
//compt_glob++;
}
}
pthread_exit(0);
}
int main (int argc, char **argv) {
// On parse les arguments
int c;
extern char *optarg;
extern int optind;
int method = -1;
int nb_t = -1;
int ite = -1;
int v = 0; //verbose
while ((c = getopt(argc, argv, "m:t:i:v")) != -1) {
switch (c) {
case 'm':
method = atoi(optarg);
if (method != 1 && method != 2) err_args();
break;
case 't':
nb_t = atoi(optarg);
if (nb_t > 16) err_args();
break;
case 'i':
ite = atoi(optarg);
break;
case 'v':
v = 1;
break;
default:
err_args();
break;
}
}
if (method < 0 || nb_t < 0 || ite < 0) err_args();
printf("Lancement du programme...\nMéthode %d, %d thread(s) et %d itération(s)\n", method, nb_t, ite);
//Fichier de sauvegarde
FILE* fichier = NULL;
fichier = fopen("calcul.txt", "w");
fprintf(fichier, "Méthode %d - %d thread(s) - %d itération(s)\n", method, nb_t, ite);
//On initialise les tableaux
//srand(time(NULL));
if (!v) goto no_verbose1;
srand(0);
for (int i = 0; i < D; ++i){
V[i] = (rand() % 20) - 10;
V_plus[i] = 0;
for (int j = 0; j < D; ++j)
A[i][j] = (rand() % 20) - 10;
}
printf("Tableaux initialisés : \nV(0) = [ ");
for (int i = 0; i < D; ++i)
printf("%d, ", V[i]);
printf("]\n");
printf("A = [\n");
for (int i = 0; i < D; ++i){
for (int j = 0; j < D; ++j)
printf("%d, ", A[i][j]);
printf("\n");
}
printf("]\n");
no_verbose1:
;
struct timeval begin, end;
gettimeofday(&begin, NULL);
pthread_t threads[nb_t];
for (int it = 0; it < ite; ++it){
// Lancement des threads en fonction de la méthode
for (int j = 0; j < nb_t; ++j) {
if (method == 1) pthread_create(&threads[j], NULL, fn_thread_m1, (void*) &nb_t);
else pthread_create(&threads[j], NULL, fn_thread_m2, (void*) &nb_t);
}
// On attend que tout les threads finissent leur partie
for (int i = 0; i < nb_t; ++i) pthread_join(threads[i], NULL);
for (int i = 0; i < D; ++i) {V[i] = V_plus[i]; V_plus[i] = 0;}
t_num = 0;
// On affiche le vecteur calculé
if (!v) goto no_verbose2;
printf("V(%d) = [ ", it + 1);
for (int i = 0; i < D; ++i)
printf("%d, ", V[i]);
printf("]\n");
no_verbose2:;
}
gettimeofday(&end, NULL);
printf("Time: %ld microseconds\n", ((end.tv_sec - begin.tv_sec)*1000000L + end.tv_usec) - begin.tv_usec);
printf("Nombre d'opération arithmétique : %d\n", compt_glob);
printf("Enregistrement...");
fprintf(fichier, "Temps d'exécution : %ld\n", ((end.tv_sec - begin.tv_sec)*1000000L + end.tv_usec) - begin.tv_usec);
fclose(fichier);
printf("fait.\n");
return 0;
}