Come programmare l'allocazione dei thread su processori multicore?


13

Vorrei sperimentare i thread su un processore multi-core, ad esempio per creare un programma che utilizza due thread diversi che vengono eseguiti da due diversi core del processore.

Tuttavia, non mi è chiaro a quale livello i thread vengono assegnati ai diversi core. Posso immaginare i seguenti scenari (a seconda del sistema operativo e dell'implementazione del linguaggio di programmazione):

  1. L'allocazione del thread è gestita dal sistema operativo. I thread vengono creati utilizzando le chiamate di sistema del sistema operativo e, se il processo viene eseguito su un processore multi-core, il sistema operativo tenta automaticamente di allocare / pianificare thread diversi su core diversi.
  2. L'allocazione del thread è gestita dall'implementazione del linguaggio di programmazione. L'assegnazione di thread a core diversi richiede chiamate di sistema speciali, ma le librerie di thread standard del linguaggio di programmazione lo gestiscono automaticamente quando utilizzo l'implementazione di thread standard per quel linguaggio.
  3. L'allocazione del thread deve essere programmata esplicitamente. Nel mio programma devo scrivere un codice esplicito per rilevare quanti core sono disponibili e allocare thread diversi su core diversi usando, ad esempio, le funzioni di libreria.

Per rendere la domanda più specifica, immagina di aver scritto la mia applicazione multi-thread in Java o C ++ su Windows o Linux. La mia applicazione vedrà e utilizzerà magicamente più core quando viene eseguita su un processore multi-core (perché tutto è gestito dal sistema operativo o dalla libreria di thread standard) o devo modificare il mio codice per essere consapevole dei più core ?

Risposte:


11

La mia applicazione vedrà e utilizzerà magicamente più core quando viene eseguita su un processore multi-core (perché tutto è gestito dal sistema operativo o dalla libreria di thread standard) o devo modificare il mio codice per essere consapevole dei più core ?

Risposta semplice: Sì, in genere verrà gestita dal sistema operativo o dalla libreria di threading.

Il sottosistema di threading nel sistema operativo assegnerà i thread ai processori in via prioritaria (opzione 1). In altre parole, quando un thread ha terminato l'esecuzione per l'allocazione o i blocchi di tempo, lo scheduler cerca il thread con priorità più alta successivo e lo assegna alla CPU. I dettagli variano da sistema operativo a sistema operativo.

Detto questo, esistono le opzioni 2 (gestite dal linguaggio di programmazione) e 3 (esplicitamente). Ad esempio, la libreria Tasks e async / wait nelle ultime versioni di .Net offrono allo sviluppatore un modo molto più semplice per scrivere codice parallelizzabile (cioè che può essere eseguito contemporaneamente a se stesso). I linguaggi di programmazione funzionale sono intrinsecamente parallelizzabili e alcuni runtime eseguiranno diverse parti del programma in parallelo, se possibile.

Per quanto riguarda l'opzione 3 (esplicitamente), Windows consente di impostare l'affinità del thread (specificando su quali processori può essere eseguito un thread). Tuttavia, questo di solito non è necessario in tutti i sistemi, tranne i più veloci, con tempi di risposta critici. L'effettiva allocazione da thread a processore dipende fortemente dall'hardware ed è molto sensibile alle altre applicazioni in esecuzione contemporaneamente.

Se vuoi sperimentare, crea un'attività a lunga durata e intensiva per la CPU come la generazione di un elenco di numeri primi o la creazione di un set di Mandelbrot. Ora crea due thread nella tua libreria preferita ed esegui entrambi i thread su una macchina multi-processore (in altre parole, praticamente qualsiasi cosa rilasciata negli ultimi anni). Entrambe le attività dovrebbero essere completate all'incirca nello stesso momento perché eseguite in parallelo.


Grazie per la spiegazione (+1). Il mio programma di test è un'implementazione di tipo merge. Nella fase divisa, voglio creare thread diversi purché siano disponibili core. Ad esempio, con due core, ogni metà di un array verrebbe ordinata da un thread / core diverso. Durante l'unione i thread superflui verrebbero quindi uniti / terminati.
Giorgio

L'ordinamento è difficile da parallelizzare in questo modo se i dati vengono distribuiti in modo casuale. Sì, puoi scomporlo e quindi ordinare ogni porzione in un thread diverso ma alla fine devi unire tutte le porzioni insieme, comunque. Se i thread condividono strutture di dati, è possibile che si verifichino problemi di contesa o blocco. Non sto dicendo che l'ordinamento non possa beneficiare del threading ma non sarà un miglioramento lineare delle prestazioni.
Akton

Le due metà di un array possono essere ordinate in modo indipendente perché non vengono condivisi dati. Solo la prima divisione e l'ultima unione dovranno essere eseguite da un thread manipolando l'intero array o elenco contenente i dati. Ciò significa che una scansione completa dei dati non può essere eseguita in parallelo; tutte le scansioni rimanenti possono.
Giorgio

Certo, considero anche i tuoi esempi come buoni candidati. Al momento ho solo una maggiore familiarità con l'ordinamento in fusione (e ne ho implementato una versione non parallela), che potrebbe (forse) rendere l'ordinamento in fusione più adatto a me come primo tentativo.
Giorgio

2
Aggiungerei a questa risposta che i buoni sistemi operativi sono abbastanza intelligenti da bilanciare il costo di assegnare un'attività a una fascia oraria su una CPU o core diversa con quella della fame a breve termine. Sulle architetture in cui conta, il risultato tende ad assomigliare all'affinità automagica. Il sistema operativo è stato creato per far sì che tutti i lavori vengano eseguiti il ​​più rapidamente possibile e potresti spararti ai piedi legando i fili ai core e ostacolando la sua capacità di prendere quelle decisioni.
Blrfl

-1

Una volta avevo un enorme ambiente SGI IRIX. Solo per diamine, ho scritto un piccolo programma java multi-thread (che non ha fatto altro che consumare cicli di CPU) e creato 12 thread in esso. Il lavoro si è svolto su 12 CPU nell'architettura NUMA. Forse cercherò il programma, lo eseguirò sul Dell R910 e controllerò ...


3
Questa risposta non aggiunge molto alla risposta esistente. Forse se hai spiegato perché la JVM sul sistema SGI ha assegnato i thread al core ...
Jay Elston,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.