pthread_join pthread_create pthread multithreading cpu processor affinity

multithreading - pthread_join - pthread_create c++



cómo establecer la afinidad de CPU de un pthread particular? (5)

Asumiendo linux:

La interfaz para establecer la afinidad es, como probablemente ya haya descubierto:

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

Pasar 0 como el pid, y se aplicará solo al hilo actual, o hacer que otro hilo informe su pid de kernel con la llamada específica de linux pid_t gettid (void); y pasar eso como el pid.

Citando la página man

La máscara de afinidad es en realidad un atributo por subproceso que se puede ajustar independientemente para cada uno de los subprocesos en un grupo de subprocesos. El valor devuelto por una llamada a gettid (2) se puede pasar en el argumento pid. Especificar pid como 0 establecerá el atributo para el hilo de llamada, y pasar el valor devuelto por una llamada a getpid (2) establecerá el atributo para el hilo principal del grupo de hilos. (Si está utilizando la API de subprocesos POSIX, utilice pthread_setaffinity_np (3) en lugar de sched_setaffinity ()).

Me gustaría especificar la afinidad de cpu de un pthread particular. Todas las referencias que he encontrado hasta ahora tratan de establecer la afinidad de CPU de un proceso (pid_t) no de un hilo (pthread_t). Probé algunos experimentos pasando pthread_t alrededor y como era de esperar, fallaron. ¿Estoy tratando de hacer algo imposible? Si no, ¿puedes enviar un puntero, por favor? Un millón de gracias.


El planificador cambiará la afinidad de la CPU según lo crea conveniente; para establecerlo persistentemente, consulte cpuset en el sistema de archivos / proc.

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

O puede escribir un programa corto que establezca la afinidad de la CPU periódicamente (cada pocos segundos) con sched_setaffinity


Encuentre el siguiente programa de ejemplo para cpu-affinity de un pthread particular.

Por favor agregue las librerías apropiadas.

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); }

Compile el programa anterior con el indicador -D_GNU_SOURCE.


Este es un envoltorio que he hecho para hacerme la vida más fácil. Su efecto es que el hilo que llama se "atasca" en el núcleo 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); }


//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; }

En el entorno POSIX puede usar cpusets para controlar qué CPU pueden usar procesos o pthreads. Este tipo de control se llama afinidad de la CPU.

La función ''sched_setaffinity'' recibe pthread IDs y un cpuset como parámetro. Cuando usa 0 en el primer parámetro, el hilo que llama se verá afectado