2016-04-13 29 views
9

Comportamento desiderato: eseguire un programma Linux multi-thread su un set di core che sono stati isolati utilizzando isolcpus.Perché l'uso di taskset per eseguire un programma Linux multi-thread su un insieme di core isolati fa sì che tutti i thread vengano eseguiti su un core?

Ecco un piccolo programma che possiamo usare come esempio multi-threaded programma:

#include <stdio.h> 
#include <pthread.h> 
#include <err.h> 
#include <unistd.h> 
#include <stdlib.h> 

#define NTHR 16 
#define TIME 60 * 5 

void * 
do_stuff(void *arg) 
{ 
    int i = 0; 

    (void) arg; 
    while (1) { 
     i += i; 
     usleep(10000); /* dont dominate CPU */ 
    } 
} 

int 
main(void) 
{ 
    pthread_t threads[NTHR]; 
    int  rv, i; 

    for (i = 0; i < NTHR; i++) { 
     rv = pthread_create(&threads[i], NULL, do_stuff, NULL); 
     if (rv) { 
      perror("pthread_create"); 
      return (EXIT_FAILURE); 
     } 
    } 
    sleep(TIME); 
    exit(EXIT_SUCCESS); 
} 

Se compilare ed eseguire questo su un kernel senza CPU isolati, poi i fili sono distribuite sui miei 4 CPU . Buona!

Ora, se aggiungo isolcpus=2,3 alla riga di comando del kernel e il riavvio:

  • L'esecuzione del programma senza taskset distribuisce le discussioni su core 0 e 1. Questo è previsto come la maschera di default affinità ora esclude core 2 e 3
  • L'esecuzione con taskset -c 0,1 ha lo stesso effetto. Buona.
  • L'esecuzione di taskset -c 2,3 fa sì che tutti i thread vadano sullo stesso core (core 2 o 3). Questo è indesiderato. I thread dovrebbero distribuire su core 2 e 3. Giusto?

This post descrive un problema simile (anche se l'esempio fornito è più lontano dall'API pthreads). L'OP era felice di aggirarlo utilizzando un diverso programma di pianificazione. Non sono sicuro che questo sia l'ideale per il mio caso d'uso comunque.

C'è un modo per distribuire i thread sui core isolati utilizzando lo scheduler predefinito?

Si tratta di un bug del kernel che dovrei segnalare?

EDIT:

La cosa giusta in effetti succede se si utilizza uno scheduler real-time, come lo scheduler FIFO. Vedere man sched e man chrt per i dettagli.

+0

Personalmente, non mi sarei mai aspettato un simile comportamento. Invia un'email a LKML per verificare perché lo scheduler predefinito non è in grado di migrare su core isolati che sono stati assegnati tramite 'taskset'. – Claudio

risposta

3

Dal Linux Kernel Parametro Doc:

Questa opzione può essere utilizzata per specificare una o più CPU per isolare dalle algoritmi di bilanciamento generale SMP e la pianificazione.

Quindi, questa opzione impedirebbe efficacemente all'utilità di pianificazione di eseguire la migrazione dei thread da un core a un altro core meno conteso (bilanciamento SMP). Come tipico isolcpus vengono utilizzati insieme al controllo di affinità pthread per bloccare i thread con la conoscenza del layout della CPU per ottenere prestazioni prevedibili.

https://www.kernel.org/doc/Documentation/kernel-parameters.txt

--Edit--

Ok vedo il motivo per cui si sono confusi. Sì, personalmente assumerei un comportamento coerente su questa opzione. Il problema si trova attorno a due funzioni, select_task_rq_fair e select_task_rq_rt, che è responsabile della selezione di nuovo run_queue (che essenzialmente seleziona quale next_cpu deve essere eseguito). Ho fatto una rapida traccia (Systemtap) di entrambe le funzioni, per CFS avrebbe sempre restituito lo stesso primo core nella maschera; per RT, restituirebbe altri core.Non ho la possibilità di esaminare la logica in ogni algoritmo di selezione, ma puoi inviare una e-mail al mantainer nella lista di distribuzione di Devel Linux per la correzione.

+0

OK, ma non capisco perché i thread si diffondano quando sono forzati su core isolati e viene utilizzato uno scheduler in tempo reale (ad esempio fifo) al posto dello scheduler predefinito. –

+0

@EddBarrett Traccia come il parametro 'isolcpus' viene interpretato negli scheduler predefiniti e RT per ottenere l'implementazione esatta all'interno del kernel di Linux. Questo sarebbe 'sched.c' contro' sched_rt.c' (per le versioni precedenti) o 'sched/core.c' e' sched/rt.c' nelle versioni più recenti del kernel Linux. – TheCodeArtist

+0

Grazie per la modifica. –