PDA

Visualizza la versione completa : [C] - Problema con Pthreads


88Leo88
21-01-2013, 21:27
Ciao a tutti,

Sono nuovo del forum e sto cercando di imparare a programmare da autodidatta visto che lavoro di già.

Mi sono imbattuto ieri in questo esercizio:
Scrivere un programma che attiva una serie di thread per effettuare il calcolo approssimato di PiGreco.

Il programma principale prende come input da riga di comando un parametro che indica il grado di accuratezza (accuracy) per il calcolo di π e il tempo massimo di attesa dopo cui il main interrompe tutti i thread.

I thread vengono utilizzati (cercando di massimizzare il numero di operazioni effettuate nel lasso di tempo a disposizione) per effettuare le seguenti operazioni per il calcolo di π tramite la serie di Gregory-Leibniz: π = 4/1 − 4/3 + 4/5 − 4/7 + 4/9 − 4/11 ...

I thread vengono tutti interrotti quando una delle due condizioni seguenti risulta verificata:
 1) il tempo massimo di attesa è stato superato;

2) la differenza tra il valore stimato di π e il valore Math.PI è minore di accuracy.


E' un esercizio che devo svolgere in C con l'ausilio dei Pthread.
La soluzione a cui avevo pensato è la seguente:


#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include <math.h>
#include <unistd.h>

int check = 0;
int MAX_THREADS = 4;

void *thread_function(void *arg)
{
float pi_greco = 0;
float pi_grecotot = 0;
float error;
int i = 0;
int denominatore = 1;
float accuracy;
accuracy =*(float*)arg;
do {
if (i%2 == 0) {
pi_greco = (float)4 / (float) denominatore;
denominatore = denominatore + 2;
}
else{
pi_greco = -(float)4 / (float)denominatore;
denominatore = denominatore + 2;
}
pi_grecotot = pi_grecotot + pi_greco;
i++;
error = pi_grecotot - M_PI;
} while (fabs(error) > accuracy && check == 0);
printf("Il valore di pigreco approssimato a %f è %f\n", accuracy, pi_grecotot);
return NULL;

}

void *thread_check_time(void *arg)
{
int t_max;
t_max = *(int*)arg;
if (t_max == 0)
{
printf("Impossibile procedere tempo inserito uguale a 0");
}
sleep(t_max);
check = 1;
return NULL;
}


int main()
{
int t_max;
float accuracy;
printf("inserisci il tempo massimo di attesa(espresso in secondi): ");
scanf("%d", &t_max);
printf("inserisci il grado di accuratezza");
scanf("%f", &accuracy);
pthread_t thread_time;
pthread_t thread_leibniz;
pthread_create(&thread_time, NULL, thread_check_time, &t_max);
pthread_create(&thread_leibniz, NULL, thread_function, &accuracy);
}


Ho riscontrato però questi problemi:
1) Non riesco a far rispettare le due condizioni di uscita ovvero o timeout oppure l'errore è maggiore di accuracy
2) Rileggendo il testo sembrerebbe che io debba lanciare N threads (al fine forse di sfruttare tutti i core del processore) ma non riesco a suddividere ulteriormente il programma in più rispetto a come ho fatto io......

c'è qualcuno che può darmi una mano??

Grazie

88Leo88
22-01-2013, 11:48
Non c'è un'anima pia che mi può spiegare dove sbaglio e come sistemare il codice???!!

Praticamente io dovrei sfruttare tutti i core della macchina e quindi dovrei usare 3 thread per i calcoli sempre nella stessa funzione thread_leibniz

mi dite come posso fare???

shodan
22-01-2013, 12:03
Prima di uscire dal main() metti dei pthread_join() per essere sicuro che i thread finiscano, altrimenti finito il main(), finito tutto.
Poi non vedo il senso di mettere una sleep() in un thread per aspettare un altro thread, dato che solo il thread che la contiene viene sospeso: quella sleep() va lasciata nel main().
Infine se lanci più di un thread per il calcolo devi mettere un mutex per proteggere la variabile accuracy interna alla funzione thread che in realtà è globale visto che la passi da fuori.

88Leo88
22-01-2013, 12:28
La sleep l'avevo inserita al fine di rispettare una della condizioni della traccia.

In maniera pratica perchè io altrimenti ti giuro non capisco come sistemeresti il codice?

shodan
22-01-2013, 13:20
Originariamente inviato da 88Leo88
In maniera pratica perchè io altrimenti ti giuro non capisco come sistemeresti il codice?
Non m'intendo molto di pthread quindi prendili come suggerimenti di massima (nel senso che poi dovrai mettere le giuste funzioni)


/* variabile globale di tipo mutex fornita dai pthreads */
var global_mutex;
/* variabile di controllo globale da proteggere con un mutex */
int exit_from_thread;
int main()
{
int t_max;
float accuracy;
printf("inserisci il tempo massimo di attesa(espresso in secondi): ");
scanf("%d", &t_max);
printf("inserisci il grado di accuratezza");
scanf("%f", &accuracy);
pthread_t thread_leibniz;
exit_from_thread = 0;

/* pseudo codice */
init_mutex( global_mutex );

pthread_create(&thread_leibniz, NULL, thread_function, &accuracy);
sleep(t_max); /* sospende il main per tot tempo */

/* pseudo codice per la critical region */
mutex_lock( global_mutex )
exit_from_thread=1;
mutex_unlock ( global_mutex );

pthread_join(thread_leibniz);

}

void *thread_function(void *arg)
{
...
/* variabile temporanea */
int request_for_exit = 0;
do {
...
/* mai uscire dalla funzione senza aver rilasciato il mutex o si blocca tutto */
mutex_lock( global_mutex )
if (exit_from_thread==1) {
request_for_exit = 1;
}
mutex_unlock ( global_mutex );

} while (fabs(error) > accuracy && check == 0 && request_for_exit !=0 );
printf("Il valore di pigreco approssimato a %f è %f\n", accuracy, pi_grecotot);
return NULL;

}

Loading