2011-06-17 21 views
24

Sono nuovo in questo tipo di programmazione e ho bisogno del tuo punto di vista.Multithreading vs multiprocessing

Devo compilare un'applicazione ma non riesco a farla calcolare abbastanza velocemente. Ho già provato Intel TBB, ed è facile da usare, ma non ho mai usato altre librerie.

Nella programmazione multiprocessore, sto leggendo su OpenMP e Boost per il multithreading, ma non conosco i loro pro e contro.

In C++, quando la programmazione multi-thread è vantaggiosa rispetto alla programmazione multiprocessore e viceversa? Quale è la soluzione migliore per i calcoli pesanti o l'avvio di molte attività ...? Quali sono i loro pro e contro quando costruiamo un'applicazione progettata con loro? E infine, con quale libreria è meglio lavorare?

+1

In una macchina multiprocessore che utilizza una libreria di thread come boost si avvantaggiano dei nuclei disponibili. Puoi anche avere più thread su un processore che può essere interlivellato con tecnologie come hyperthreading in Pentium 4. Intendevi multiprocesso e un sistema distribuito o multi-threading? Puoi fare entrambe le cose, ma la natura dei thread è ottenere il parallelismo indipendentemente dal processore. FYI boost si basa su thread di posix per quanto ne so e lo trovo abbastanza facile da usare. Anche il nuovo standard C++ 0x includerà il supporto del thread nativo alla lingua. – AJG85

+0

Cosa ne pensi di Boost e Intel TBB? È più veloce di Intel TBB? O dovrei andare per Intel se ho un processore Intel? – Nazka

+0

Intel TBB ha il vantaggio in alcune aree in cui fornisce primitive parallele ottimizzate come loop paralleli, ecc., Che aiutano nella creazione di algoritmi di stile scatter-gather parallelo su processori Intel, nonché altri calcoli paralleli. Boost threads è principalmente un pacchetto di threading multipiattaforma che verrà eseguito su molti tipi di piattaforme hardware e SO. Se invece hai bisogno di alcune primitive di calcolo parallelo, i thread Boost non forniscono direttamente questo, dovresti codificarli da soli. Quindi potresti considerare TBB come un'astrazione di livello superiore rispetto a Boost. – Jason

risposta

50

Multithreading significa esattamente questo, esecuzione di più thread. Questo può essere fatto su un sistema uni-processor o su un sistema multiprocessore.

Su un sistema a processore singolo, quando si eseguono più thread, l'osservazione effettiva del computer che fa più cose contemporaneamente (ad esempio, il multi-tasking) è un'illusione, perché ciò che sta realmente accadendo sotto il cofano è che lì è un programmatore software che esegue il time-slicing sulla singola CPU. Quindi solo una singola attività sta accadendo in un dato momento, ma lo schedulatore sta passando da un'attività abbastanza veloce in modo che non si noti mai che ci sono più processi, thread, ecc. Che si contendono la stessa risorsa CPU.

Su un sistema multiprocessore, la necessità di time-slicing è ridotta. L'effetto del time-slicing è ancora lì, perché un SO moderno potrebbe avere centinaia di thread che contendono due o più processori, e in genere non c'è mai una relazione 1 a 1 nel numero di thread al numero di core di elaborazione disponibili. Quindi a un certo punto, un thread dovrà fermarsi e un altro thread inizia su una CPU condivisa dai due thread. Questo è di nuovo gestito dallo scheduler del SO. Detto questo, con un sistema multiprocessore, si può avere due cose che accadono allo stesso tempo, a differenza con il sistema uni-processor.

Alla fine, i due paradigmi sono davvero un po 'ortogonali nel senso che è necessario il multithreading ogni volta che si desidera avere due o più attività in esecuzione in modo asincrono, ma a causa del time-slicing, non è necessario necessariamente un multi- sistema di processore per farlo. Se si sta tentando di eseguire più thread e si sta svolgendo un'attività altamente parallela (ovvero, si tenta di risolvere un integrale), allora sì, più core si possono generare in un problema, meglio è. Non avrai necessariamente bisogno di una relazione 1-a-1 tra thread e core di elaborazione, ma allo stesso tempo, non vuoi far girare così tanti thread che finisci con tonnellate di thread inattivi perché devono aspettare essere programmato su uno dei core della CPU disponibili. D'altra parte, se le tue attività parallele richiedono un componente sequenziale, cioè un thread attenderà il risultato da un altro thread prima che possa continuare, allora potresti essere in grado di eseguire più thread con qualche tipo di barriera o metodo di sincronizzazione in modo tale che i thread che devono essere inattivi non girano via usando il tempo della CPU, e solo i thread che devono essere eseguiti contendono le risorse della CPU.

+2

Dang digiti veloce! Aggiungerò solo i miei due centesimi come commento. – AJG85

+0

Tutto il commento è ottimo per me :) @ Jason, quindi il thread è progettato per programmare gran parte dell'app e fare il loro lavoro no? – Nazka

+0

Un thread può essere utilizzato per un'attività ... quell'attività può essere qualsiasi cosa. Potrebbe essere qualcosa che esegue l'intera durata del tuo programma, come un demone di rete che "ascolta" le connessioni su un socket e quindi spegne più thread per gestire tali connessioni. Un thread può anche essere utilizzato per un piccolo compito come risolvere un'iterazione di un integrale che è un'attività altamente parallela. – Jason

2

Per rispondere alla prima domanda: L'approccio migliore è utilizzare le tecniche di multithreading nel codice finché non si arriva al punto in cui anche questo non offre vantaggi sufficienti. Supponiamo che il sistema operativo gestisca la delega a più processori, se disponibili.

Se si sta effettivamente lavorando su un problema in cui il multithreading non è sufficiente, anche con più processori (o se si esegue su un sistema operativo che non utilizza i suoi processori multipli), allora si può preoccupare di scoprire come per ottenere più potenza. Che potrebbe significare processi di spawning su una rete ad altre macchine.

Non ho usato TBB, ma ho usato IPP e trovato ad essere efficiente e ben progettato. Boost è portatile.

20

ci sono alcuni punti importanti che a mio avviso dovrebbe essere aggiunto alla ottima risposta da @ Jason.

Innanzitutto, multithreading non è sempre un'illusione anche su un singolo processore - ci sono operazioni che non coinvolgono il processore. Questi sono principalmente I/O - disco, rete, terminale ecc La forma di base per tale operazione è blocco o sincrono, cioè il programma attende fino al completamento dell'operazione e poi procede. In attesa, la CPU passa a un altro processo/thread.

se avete qualcosa che si può fare in quel periodo (ad esempio sfondo di calcolo in attesa di input da parte dell'utente, che serve una nuova richiesta, ecc) si deve fondamentalmente due opzioni:

  • uso I/O asincrono : si chiama un non-blocking I/O dotandola di una funzione di callback , dicendogli "chiamata questa funzione quando si è fatto". La chiamata ritorna immediatamente e l'operazione I/O continua in background. Vai avanti con l'altra roba.

  • utilizzare il multithreading: si dispone di un thread dedicato per ogni tipo di attività. Mentre si attende il blocco della chiamata I/O, l'altro continua.

Entrambi gli approcci sono difficili paradigmi di programmazione, ognuno ha i suoi pro e contro.

  • con I/O asincrono la logica della logica del programma è meno ovvia ed è difficile da seguire e eseguire il debug. Tuttavia si evitano problemi thread-safe.
  • con fili, la sfida è scrivere thread-safe programmi. I difetti di sicurezza del thread sono bug sgradevoli che sono abbastanza difficili da riprodurre. L'uso eccessivo del blocco può effettivamente portare a un degrado invece di migliorare le prestazioni.

(venire al multi-processing)

Multithreading reso popolare in Windows perché manipolazione processi è abbastanza pesante su Windows (creazione di un processo, commutazione contesto etc.) al contrario di fili che sono molto più leggero (almeno questo è stato il caso quando ho lavorato su Win2K).

Su Linux/Unix, i processi sono molto più leggeri. Anche i thread (AFAIK) su Linux sono implementati in realtà come una sorta di processi internamente, quindi non vi è alcun guadagno nel cambio di contesto dei thread rispetto ai processi. Tuttavia, è necessario utilizzare una qualche forma di IPC (comunicazioni tra processi) come memoria condivisa, pipe, coda messaggi ecc.

Su una nota più lite, guarda il SQLite FAQ, che dichiara "I thread sono cattivi"!:)

+2

C'è anche una terza opzione, multiplexing dell'I/O tramite select()/poll()/etc. Questo può essere più sicuro del multithreading e più facile da capire rispetto all'I/O asincrono. –

0

Volevo solo ricordare che il paradigma di programmazione basata sul flusso (http://www.jpaulmorrison.com/fbp) è un approccio multiprogrammazione/multiprocesso naturale allo sviluppo di applicazioni. Fornisce una vista applicativa coerente dal livello alto al livello basso. Le implementazioni Java e C# sfruttano tutti i processori sulla tua macchina, ma l'implementazione C++ più vecchia utilizza solo un processore. Tuttavia, potrebbe essere facilmente esteso per utilizzare BOOST (o pthreads, suppongo) mediante l'uso del locking sulle connessioni. Avevo iniziato a convertirlo per usare le fibre, ma non sono sicuro che ci sia un qualche motivo per continuare su questa rotta. :-) Il feedback sarebbe apprezzato. BTW Le implementazioni Java e C# possono persino comunicare tra loro tramite i socket.