Me gustaría especificar la afinidad de CPU de un pthread en particular. Todas las referencias que he encontrado hasta ahora tratan de establecer la afinidad de CPU de un proceso (pid_t
) no es un hilo (pthread_t
). Probé algunos experimentos pasando pthread_t
‘s alrededor y como era de esperar que fallan. ¿Estoy tratando de hacer algo imposible? Si no, ¿puedes enviar un puntero por favor? Un millón de gracias.
Eduardo Bezerra
Este es un envoltorio que he hecho para hacerme la vida más fácil. Su efecto es que el subproceso de llamada se “pega” al 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);
}
-
Para referencia futura: es necesario agregar #define _GNU_SOURCE e #include
para trabajar en gcc 4.7.2. Funcionó perfectamente en arch linux, probado con oprofile y pthread. – John Tortugo
19 de mayo de 2013 a las 4:40
-
También,
#include <unistd.h>
se necesita parasysconf
congcc 4.8.1
.– Brandon Amós
13 de septiembre de 2013 a las 16:36
-
Por alguna razón, funciona en mi computadora con dos núcleos, sin embargo, en mi otra computadora con 4 núcleos da el siguiente error:
Error de segmentación (núcleo volcado)
– oneiros
14/09/2013 a las 22:49
-
Lindo. En lugar de fallar cuando core_id > num_cores, otro parámetro podría especificar el valor predeterminado en ese caso:
core_id = default_core
; -1 como valor predeterminado podría significar fallar.–Brent Fausto
18 de febrero de 2014 a las 18:01
-
que es mejor usar este codigo o
sched_setaffinity
de @nos respuesta a continuación?– Oleg Vazhnev
19/09/2014 a las 12:30
nos
Asumiendo Linux:
La interfaz para configurar la afinidad es, como probablemente ya haya descubierto:
int sched_setaffinity(pid_t pid,size_t cpusetsize,cpu_set_t *mask);
Al pasar 0 como el pid, se aplicará solo al subproceso actual, o hará que otros subprocesos informen su pid del kernel con la llamada específica de Linux pid_t gettid(void);
y pasar eso como el pid.
citando el página man
La máscara de afinidad es en realidad un atributo por subproceso que se puede ajustar de forma independiente para cada uno de los subprocesos de 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 subproceso de llamada, y pasar el valor devuelto de una llamada a getpid(2) establecerá el atributo para el subproceso principal del grupo de subprocesos. (Si está utilizando la API de subprocesos POSIX, utilice pthread_setaffinity_np (3) en lugar de sched_setaffinity()).
-
“Si está utilizando la API de subprocesos POSIX, utilice pthread_setaffinity_np (3) en lugar de sched_setaffinity()”. ¿Cómo debo saber si estoy usando la API POSIX? Cómo seleccionar el uso
sched_setaffinity
opthread_setaffinity_np
?– Oleg Vazhnev
24 de noviembre de 2014 a las 10:41
-
en RHEL 7 esto es lo que dice el hombre
If pid is zero, then the calling process is used.
(proceso, no hilo)– Oleg Vazhnev
26 de noviembre de 2014 a las 19:19
-
@javapowered Esa oración en la página del manual es incorrecta. Lea también la sección de NOTAS.
– nos
26 de noviembre de 2014 a las 20:43
-
Tengo el mismo problema pero estoy usando OS X. ¿Existe un método similar?
– Raghav
9 de abril de 2015 a las 3:43
-
@Raghav OS X no expone la funcionalidad para anclar subprocesos a núcleos específicos.
– zgerd
16 de abril de 2020 a las 1:26
//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 los procesos o pthreads. Este tipo de control se denomina afinidad de CPU.
La función ‘sched_setaffinity’ recibe ID de pthread y un cpuset como parámetro. Cuando usa 0 en el primer parámetro, el hilo de llamada se verá afectado
yugireddy
Encuentre el siguiente programa de ejemplo para la afinidad de la CPU de un pthread en particular.
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.
El planificador cambiará la afinidad de la CPU como mejor le parezca; para configurarlo de forma persistente, 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