PDA

Visualizza la versione completa : [C++] Giustificare l'uso di più thread


misterx
11-08-2011, 18:27
ho implementato un programma con due thread il cui scopo è leggere dati da schede, verificare se tali dati sono cambiati e se lo sono, visualizzare i risultati.

Ero molto indeciso se scrivere tutto il programma in sequenza oppure adottare la strada dei thread per introdurre un certo parallelismo ed ho pensato: se il numero di schede da analizzare si limita ad una allora l'uso dei thread forse non è giustificabile ma se il numero di schede è maggiore di una allora l'uso dei thread trova la sua giustificazione. Per fare un esempio avrei che, in quanto io accedo alle varie schede attraverso indirizzo ip:

//caso senza thread
schede[]={192.168.80.10, 192.168.80.11, 192.168.80.20};
byte buffer[512];
num_schede=3;
for (int i =0; i< num_schede; i++ ){

buffer = leggischeda(schede[i]);

for( int u = 0; u < 512; u++){
if(buffer[u] == ...... ) se è cambiato qualcosa allora visualizza e salva
}

in questo scenario le altre schede attendono il termine dell'esecuzione della scheda che la precede
}

//caso con thread
schede[]={192.168.80.10, 192.168.80.11, 192.168.80.20};
byte buffer[512];

//thread lettore scheda
threadLettore(char *ip)
{
buffer = leggischeda(ip);
for( int u = 0; u < 512; u++){
if(buffer[u] == ...... ) se è cambiato qualcosa allora visualizza e salva

}

//thread visualizza e salva
prinft();
fprintf();

in questo secondo scenario nessuna scheda attende l'altra e tutto si muove in parallelo.

Vi pare un pensata valida?


grazie


p.s.
3 schede sono solo un esempio in quanto potrebbero essere maggiori di 10

MacApp
11-08-2011, 21:03
prova sia in modo seriale che multithread, poi trai da solo le tue conclusioni ;-)

Attento che la programmazione multithread non è semplice..

valia
12-08-2011, 09:15
soprattutto prova con numeri significativi: con i calcolatori odierni 3/10 schede è niente, prova a metterne almeno un centinaio (e/o salire in ordine di grandezza anche ad un migliaio).

Ricorda anche che il parallelismo è fittizio (anche se hai 2 processori non è detto che il tuo programma li richiami entrambi, puoi gestire tutto con un solo processore) e dipende anche da altri fattori (ad esempio priorità).
Per un programma del genere dovresti in un certo senso porti nella situazione tipo, da quella arrivare ai casi limiti e pensare entrambe le soluzioni nel caso limite.

Poi un consiglio: in un contesto multi-thread è bene che ogni thread sia autoconsistente (per evitare casini insomma).
Dovresti portarti dietro le info in modo da recuperarle thread per thread

misterx
12-08-2011, 11:05
Originariamente inviato da valia
soprattutto prova con numeri significativi: con i calcolatori odierni 3/10 schede è niente, prova a metterne almeno un centinaio (e/o salire in ordine di grandezza anche ad un migliaio).

Ricorda anche che il parallelismo è fittizio (anche se hai 2 processori non è detto che il tuo programma li richiami entrambi, puoi gestire tutto con un solo processore) e dipende anche da altri fattori (ad esempio priorità).
Per un programma del genere dovresti in un certo senso porti nella situazione tipo, da quella arrivare ai casi limiti e pensare entrambe le soluzioni nel caso limite.

Poi un consiglio: in un contesto multi-thread è bene che ogni thread sia autoconsistente (per evitare casini insomma).
Dovresti portarti dietro le info in modo da recuperarle thread per thread


però il lavoro "grosso" è verificare bit a bit i 512 byte delle schede quindi 512x8=4096 bit di 10 schede che ammonta a 40960 bit. Di sicuro è ancora una inezia per un calcolatore ma considerando che è traffico che viaggia in rete, beh, tutto sommato non è nemmeno molto ripensandoci :)

Ad ogni modo la soluzione a thread mi sembra la più flessibile in quanto aumentando il numero di schede posso istanziare n thread che leggono le schede e tenere solo un thread condiviso per la visualizzazione e la scrittura, ovviamente usando una qualche coda o altro tipo di struttura dati.

Che ne dite?

valia
12-08-2011, 11:12
io non ho letto in dettaglio il tuo codice, ma potresti pensare anzichè leggere l'intera scheda di aggiungere un flag "modificato" che setti alla prima modifica.
Potrebbe essere una soluzione accettabile (se puoi farlo ovviamente)

misterx
12-08-2011, 11:42
ciao,
allora valia considera questo: hai una funzione di libreria attraverso la quale puoi decidere quanti byte alla volta puoi leggere dalla scheda.

La chiamata alla funzione è del tipo LeggiScheda(indirizzoIP, buffer[]);

Fatto questo cicli il buffer e se trovi un bit modificato lo visualizzi e determini quento tempo è rimasto a zero oppure a uno; qui si tratta solo di implementare un pò di codice per calcolare lo stato precedente del bit e quello successivo.

Le schede sono n quindi se dovessi onterrogarle in modo sequenziale dovrei attendere la fine del ciclo per ogni scansione del buffer e le altre schede rimangono in attesa della prossima lettura.

Coi thread invece ogni scheda ha un suo spazio e la funzione di libreria viene chiamata parallelamente come allo stesso modo viene ciclato(scansito) parallelamente il buffer.

Qusto secondo aspetto forse giustifica l'uso dei thread in luogo di una struttura sequenziale a parer mio, però il dubbio c'è sempre.

valia
12-08-2011, 12:02
indubbiamente il thread ti velocizza, devi solo provare (e avrai qualche mal di testa per descrivere l'environment del tuo thread in modo che non si blocchi con gli altri).

Ora per quanto riguarda le specifiche, non so il tuo problema in generale, ovviamente per sapere se c'è una variazione devi mantenere tutte le schede memorizzate da qualche parte (e non è comodo) e soprattutto devi ogni volta controllare tutto il buffer (da qui dividere in thread potrebbe aiutarti).
La dimensione di quel buffer non è un parametro che scegli con leggerezza.

Vedi anche con quanta frequenza cambiano le schede: frequenza rapida devi controllare byte a byte, scrivere (per il check successivo) e avviare un nuovo confronto. Per buffer molto grandi anche coi thread puoi perderti input (ma questa è una considerazione architetturale).
Al contrario una frequenza bassa garantirebbe la consistenza dei dati, ma di contro fai una serie di operazioni non necessarie (visto che il check byte a byte ti darà true in molti casi).

Come vedi queste sono considerazioni di base che puoi fare indipendentemente dal linguaggio e sono domande che mi faccio io pensando al problema via via che dai indicazioni.

Come ti dicevo, tu se hai l'idea di insieme, io no. So solo che in ogni caso l'opzione confronta sempre e cmq il contenuto la terrei solo se obbligata

misterx
12-08-2011, 13:06
Originariamente inviato da valia
indubbiamente il thread ti velocizza, devi solo provare (e avrai qualche mal di testa per descrivere l'environment del tuo thread in modo che non si blocchi con gli altri).

questo mi è già capitato con una sola scheda, deadlock risolto risvegliando uno dei due thread ma non ho ancora scoperto cosa li blocca.

Effettivamente quello che andavo cercando erano certe prestazioni in modo che nelle pause "morte" qualcosa continuasse a lavorare, mentre una scheda viene letta magari in un'altra viene fatta la verifica bit a bit e così via senza attese sequenziali.

Non c'è modo di conoscere quando un bit cambia in una scheda e per tale motivo serve un metodo efficace e mi è sembrato proprio l'uso dei thread, ovviamente usando tutte le cautele del caso (semafori, eventi etc...).

Anche da ciò che dici tu mi è sembrato di capire che l'uso dei thread è giustificato in quanto ottengo maggiore performance, ovviamente è più difficile poi fare le cose per bene.

MacApp
12-08-2011, 23:46
Originariamente inviato da misterx
ovviamente è più difficile poi fare le cose per bene.
Attento il Deadlock o il Livelock sono situazioni "facili" da gestire: non funziona nulla e ti accorgi subito che c'è qualcosa che non va. Il difficile è quando farai (inevitabilmente) un bel mix di dati... tutto ti sembrerà funzionare correttamente, ma in realtà i dati saranno sballati ;-)

Poi quando il tutto ti funzionerà nella versione debug, ti accorgerai con la release di problemi che non sospettavi neppure potessero esistere, e scoprirai ad esempio l'oscuro significato di parole chiavi quali ad esempio... "volatile" ;-)

MItaly
12-08-2011, 23:59
Originariamente inviato da misterx
Di sicuro è ancora una inezia per un calcolatore ma considerando che è traffico che viaggia in rete
... probabilmente il bottleneck è la rete (ovvero l'IO) e non la CPU, quindi conviene fare ottimizzazioni sul formato di trasmissione sulla rete piuttosto che sull'elaborazione. :)


Ad ogni modo la soluzione a thread mi sembra la più flessibile in quanto aumentando il numero di schede posso istanziare n thread che leggono le schede e tenere solo un thread condiviso per la visualizzazione e la scrittura, ovviamente usando una qualche coda o altro tipo di struttura dati.

Il concetto è quello del thread pool (http://en.wikipedia.org/wiki/Thread_pool_pattern); in linea di massima, se non ti aspetti dei blocchi nell'elaborazione di ciascun pezzo, i thread non dovrebbero superare di molto i core effettivamente disponibili sulla macchina, dato che se esageri con i thread si perde in efficienza perché lo scheduler deve continuamente mettere in pausa un thread per schedularne un altro.

Loading