2009-09-10 16 views
51

mi piacerebbe specificare la CPU-affinità di un particolare pthread. Tutti i riferimenti che ho trovato molto finora con l'impostazione della CPU-affinità di un processo (pid_t) non un filo (pthread_t). Ho provato alcuni esperimenti passando pthread_t e, come previsto, falliscono. Sto cercando di fare qualcosa di impossibile? In caso contrario, puoi inviare un puntatore per favore? Grazie mille.come impostare CPU affinità di un particolare pthread?

risposta

36

linux Assumendo:

L'interfaccia per l'impostazione l'affinità è - come probabilmente avete già scoperto:

int sched_setaffinity(pid_t pid,size_t cpusetsize,cpu_set_t *mask); 

Passando 0 come il pid, e applicherete al thread corrente solo oppure altri thread riportano il loro pid del kernel con la chiamata specifica di linux pid_t gettid (void); e passalo come il pid.

Citando la prega di trovare il programma di esempio sotto man page

The affinity mask is actually a per-thread attribute that can be adjusted independently for each of the threads in a thread group. The value returned from a call to gettid(2) can be passed in the argument pid. Specifying pid as 0 will set the attribute for the calling thread, and passing the value returned from a call to getpid(2) will set the attribute for the main thread of the thread group. (If you are using the POSIX threads API, then use pthread_setaffinity_np (3) instead of sched_setaffinity().)

+2

"Se si utilizza il POSIX discussioni API, quindi utilizzare pthread_setaffinity_np (3) al posto di sched_setaffinity()". Come devo sapere se sto usando l'API POSIX? Come selezionare usare 'sched_setaffinity' o' pthread_setaffinity_np'? – javapowered

+0

in RHEL 7 questo è ciò che dice l'utente 'Se pid è zero, viene utilizzato il processo chiamante. (Processo, non thread) – javapowered

+0

@javapowered Quella frase nella pagina man è sbagliata. Leggi anche la sezione NOTE. – nos

-2

per cpu affinità di un particolare pthread.

Si prega di aggiungere librerie appropriate.

double waste_time(long n) 
{ 

    double res = 0; 
    long i = 0; 
    while (i <n * 200000) { 
     i++; 
     res += sqrt(i); 
    } 
    return res; 
} 

void *thread_func(void *param) 
{ 

    unsigned long mask = 1; /* processor 0 */ 

    /* bind process to processor 0 */ 
    if (pthread_setaffinity_np(pthread_self(), sizeof(mask), 
     &mask) <0) { 
     perror("pthread_setaffinity_np"); 
    } 

    /* waste some time so the work is visible with "top" */ 
    printf("result: %f\n", waste_time(2000)); 

    mask = 2; /* process switches to processor 1 now */ 
    if (pthread_setaffinity_np(pthread_self(), sizeof(mask), 
     &mask) <0) { 
     perror("pthread_setaffinity_np"); 
    } 

    /* waste some more time to see the processor switch */ 
    printf("result: %f\n", waste_time(2000)); 
} 


int main(int argc, char *argv[]) 
{ 

    pthread_t my_thread; 

    if (pthread_create(&my_thread, NULL, thread_func, NULL) != 0) { 
     perror("pthread_create"); 
    } 
    pthread_exit(NULL); 
} 

Compila il programma con il flag -D_GNU_SOURCE.

+3

Il tuo programma funzionerà, ma ci sono diversi problemi che vedo: 1) pthread_setaffinity_np accetta un cpu_set_t, non un lungo senza segno. Si dovrebbe usare CPU_SET, CPU_ZERO, ecc.macro per manipolare le maschere prima di passare alle funzioni di affinità 2) Infine, non è necessario avviare una nuova discussione con pthread_create per eseguire la parte principale del codice –

39

Questo è un wrapper che ho fatto per rendere la mia vita più facile. Il suo effetto è che il thread chiamante viene "bloccato" fino al midollo con id core_id:

// core_id = 0, 1, ... n-1, where n is the system's number of cores 

int stick_this_thread_to_core(int core_id) { 
    int num_cores = sysconf(_SC_NPROCESSORS_ONLN); 
    if (core_id < 0 || core_id >= num_cores) 
     return EINVAL; 

    cpu_set_t cpuset; 
    CPU_ZERO(&cpuset); 
    CPU_SET(core_id, &cpuset); 

    pthread_t current_thread = pthread_self();  
    return pthread_setaffinity_np(current_thread, sizeof(cpu_set_t), &cpuset); 
} 
+6

Per riferimento futuro: è necessario aggiungere #define _GNU_SOURCE e # includere per lavorare su gcc 4.7.2. Ha funzionato perfettamente su arch linux, testato con oprofile e pthread. – JohnTortugo

+0

Inoltre, '' #include è necessario per '' sysconf' con gcc 4.8.1'. –

+0

Per qualche motivo funziona sul mio computer con due core, tuttavia sul mio altro computer con 4 core si dà il seguente errore:

Segmentation fault (core dumped)
oneiros

14
//compilation: gcc -o affinity affinity.c -lpthread 

#define _GNU_SOURCE 
#include <sched.h> //cpu_set_t , CPU_SET 
#include <pthread.h> //pthread_t 
#include <stdio.h> 

void *th_func(void * arg); 

int main(void) { 
    pthread_t thread; //the thread 

    pthread_create(&thread,NULL,th_func,NULL); 

    pthread_join(thread,NULL); 

    return 0; 
} 


void *th_func(void * arg) 
{ 
    //we can set one or more bits here, each one representing a single CPU 
    cpu_set_t cpuset; 

    //the CPU we whant to use 
    int cpu = 2; 

    CPU_ZERO(&cpuset);  //clears the cpuset 
    CPU_SET(cpu , &cpuset); //set CPU 2 on cpuset 


    /* 
    * cpu affinity for the calling thread 
    * first parameter is the pid, 0 = calling thread 
    * second parameter is the size of your cpuset 
    * third param is the cpuset in which your thread will be 
    * placed. Each bit represents a CPU 
    */ 
    sched_setaffinity(0, sizeof(cpuset), &cpuset); 

    while (1); 
     ; //burns the CPU 2 

    return 0; 
} 

In ambiente POSIX è possibile utilizzare per controllare Cpusets quali CPU possono essere utilizzati da processi o pthreads. Questo tipo di controllo è chiamato affinità CPU.

La funzione 'sched_setaffinity' riceve ID pthread e un cpuset come parametro. Quando si utilizza 0 nel primo parametro, il thread chiamante sarà interessato

-2

Lo scheduler modificherà l'affinità della CPU come meglio crede; per impostarlo in modo permanente, vedere cpuset nel file system/proc.

http://man7.org/linux/man-pages/man7/cpuset.7.html

Oppure si può scrivere un breve programma che imposta l'affinità CPU periodicamente (ogni pochi secondi) con sched_setaffinity