2010-05-13 6 views
6

Eseguo lavori di calcolo scientifico in parallelo su un computer Linux condiviso con 24 core. La maggior parte delle volte i miei lavori sono in grado di ridimensionare a 24 core quando su questo computer non è in esecuzione nient'altro. Tuttavia, sembra che anche un solo lavoro a thread singolo che non è mio sia in esecuzione, i miei processi a 24 thread (che ho impostato per valori elevati) riescono a ottenere solo il 1800% di CPU (usando la notazione di Linux). Nel frattempo, circa il 500% dei cicli della CPU (di nuovo, usando la notazione di Linux) sono inattivi. Qualcuno può spiegare questo comportamento e cosa posso fare per ottenere tutti i 23 core che non vengono utilizzati da qualcun altro?Linux 2.6.31 Scheduler e lavori con multithreading

Note:

  1. Nel caso in cui sia rilevante, ho osservato questo su versioni del kernel leggermente diverse, anche se non riesco a ricordare che la parte superiore della mia testa.

  2. L'architettura della CPU è x64. È possibile che il fatto che i miei lavori a 24 core siano a 32 bit e gli altri lavori con cui sono in competizione siano a 64 bit sia rilevante?

Modifica: Una cosa che ho notato è che passare a 30 thread sembra alleviare il problema in una certa misura. Mi porta al ~ 2100% della CPU.

+0

La riaggiustamento riguarda solo i processi che si sviluppano, se si esegue solo un singolo processo che genera n thread .. beh .. si compete solo con un singolo processo. Root/sudo sono disponibili su questa macchina? –

+0

Cosa succede se si scende a 23 thread, lasciando un core disponibile per l'altro lavoro? – caf

risposta

6

È possibile che ciò sia causato dallo scheduler che tenta di mantenere ciascuna delle attività in esecuzione sulla stessa CPU in cui era in precedenza in esecuzione (lo fa perché l'attività ha probabilmente portato il proprio working set nella cache di quella CPU - è "cache hot").

Ecco alcune idee si può provare:

  • Run il doppio delle discussioni quando si dispone di nuclei;
  • Esegui uno o due thread in meno rispetto ai core;
  • Ridurre il valore di /proc/sys/kernel/sched_migration_cost (forse fino a zero);
  • Ridurre il valore di /proc/sys/kernel/sched_domain/.../imbalance_pct verso il basso più vicino a 100.
0

Potrebbe valere la pena utilizzare mpstat (parte del pacchetto sysstat) per capire se tutte le CPU sono inattive mentre altre sono completamente utilizzate. Dovrebbe fornire una vista più dettagliata dell'utilizzo rispetto a top o vmstat: eseguire mpstat -P ALL per vedere 1 riga per CPU.

Come esperimento, si potrebbe provare ad impostare l'affinità della CPU su ciascun thread in modo che ognuno sia associato a una singola CPU; questo ti permetterebbe di vedere come sono le prestazioni se non lasci che lo scheduler del kernel decida su quale CPU è programmata un'attività. Non è una buona soluzione permanente, ma se aiuta molto ti dà un'idea di dove sta andando a finire lo scheduler.

+0

Purtroppo non ho privilegi di amministratore e sysstat non è installato. – dsimcha

+1

Non è difficile creare sysstat dal sorgente. –

2

I thread devono sincronizzarsi? In tal caso, si potrebbe avere il seguente problema:

Si supponga di disporre di un sistema a 4 CPU e di un processo a 4 thread. Quando vengono eseguiti da soli, i thread si espandono per utilizzare tutti e 4 i core e l'utilizzo totale è quasi perfetto (lo chiameremo al 400%).

Se si aggiunge un lavoro di interferenza a thread singolo, lo scheduler potrebbe posizionare 2 dei thread sulla stessa CPU. Ciò significa che 2 dei tuoi thread ora funzionano a una velocità pari alla metà del loro normale ritmo (semplificazione notevole) e se i tuoi thread devono essere sincronizzati periodicamente, l'avanzamento del tuo lavoro può essere limitato dal thread più lento, che in questo caso è in esecuzione su metà della velocità normale. Vedresti un utilizzo di solo il 200% (dal tuo lavoro in esecuzione 4x 50%) più il 100% (il lavoro che interferisce) = 300%.

Analogamente, se si presume che il lavoro di interferenza utilizzi solo il 25% del tempo di un processore, è possibile visualizzare uno dei thread e l'interferente sulla stessa CPU. In quel caso il filo più lento funziona a 3/4 della velocità normale, causando un utilizzo totale del 300% (4x 75%) + 25% = 325%. Gioca con questi numeri e non è difficile trovare qualcosa di simile a quello che stai vedendo.

Se questo è il problema, puoi certamente giocare con priorità per dare compiti sgraditi solo piccole frazioni di CPU disponibile (suppongo che i ritardi di I/O non siano un fattore). Oppure, come hai trovato, prova ad aumentare i thread in modo che ogni CPU abbia, diciamo, 2 thread, meno alcuni per consentire le attività di sistema. In questo modo, un sistema a 24 core potrebbe funzionare al meglio con, ad esempio, 46 ​​thread (che lascia sempre disponibile metà dei 2 core per le attività di sistema).

+0

Ovviamente, il suggerimento di caf di 23 thread è probabilmente migliore del mio suggerimento di 46 thread come metodo per ottenere il 2300% di utilizzo. –

0

Pensi che il collo di bottiglia è nell'applicazione o algoritmo di scheduling del kernel? Prima di iniziare a modificare i parametri di pianificazione, ti suggerisco di provare a eseguire una semplice applicazione multi-thread per vedere se presenta lo stesso comportamento della tua applicazione.

// COMPILE WITH: gcc threads.c -lpthread -o thread 
#include <pthread.h> 
#define NUM_CORES 24 

void* loop_forever(void* argument) { 
    int a; 
    while(1) a++; 
} 

void main() { 
    int i; 
    pthread_t threads[NUM_CORES]; 

    for (i = 0; i < NUM_CORES; i++) 
     pthread_create(&threads[i], 0, loop_forever, 0); 

    for (i = 0; i < NUM_CORES; i++) 
     pthread_join(threads[i], 0); 
} 
1

Le tue discussioni comunicano tra loro?

Provare a collegare manualmente ogni thread alla CPU, con sched_setaffinity o pthread_setaffinity_np. Scheduler può essere piuttosto stupido quando si lavora con molti thread relativi.