2009-12-06 20 views
5

¿O está controlado por el sistema operativo? He oído que el nuevo lenguaje Go de Google tiene funciones incorporadas para que un programador sea tan granular o ¿lo he entendido mal?¿Puedo elegir y elegir mediante programación qué núcleo de una CPU multi-core debe ejecutar mi hilo?

+2

Podría ser posible, pero ¿por qué querrías hacer eso? Normalmente, el sistema operativo puede tomar decisiones mucho mejores sobre qué CPU ejecutar el código que una aplicación de espacio de usuario. –

+2

@Zach Algunos algoritmos realmente funcionan mejor si tienes un control preciso sobre lo que hace cada CPU. Por ejemplo, los algoritmos con spinlocks roll-your-own tendrán un rendimiento muy pobre si se subvierte un hilo, por lo que es mejor vincularse a un núcleo particular en cada hilo. O puedo imaginar que sea relevante para cosas muy vinculadas a la CPU. Dicho eso ... Tienes razón, eso es una especie de nicho. – asveikau

+0

@asveikau Claro, pero en qué CPU se está ejecutando no afecta si va a obtener una apropiación o no. Un caso en el que puedo pensar que importaría es en las arquitecturas NUMA. Pero dudo que el programa de espacio de usuario pueda tomar una decisión que lo beneficie mejor que elegir al azar. –

Respuesta

2

Para linux os, sched_setaffinity es su respuesta. Es compatible desde Linux kernel 2.5.8.

Nombre

sched_setaffinity, sched_getaffinity - establecer y obtener afinidad de la CPU de un proceso máscara

#define _GNU_SOURCE 
#include <sched.h> 

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

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

la máscara de afinidad es en realidad un atributo para cada subproceso que puede ser ajustar independientemente para cada uno de los hilos en un grupo de hilos. El valor devuelto de una llamada a gettid (2) puede pasar en el argumento pid. Especificación de pid como 0 establecerá el atributo para el subproceso de llamada, y pasando el valor devuelto desde una llamada a getpid (2) va a establecer el atributo para el hilo principal de la grupo de hilos. (Si está utilizando la API POSIX hilos, a continuación, utilizar pthread_setaffinity_np (3) en lugar de sched_setaffinity().)

3

Está determinado por el sistema operativo.

Puede configurar sugerencias para ello con pthread_attr_setaffinity_np().

Pero el sistema operativo puede anularlo. La llamada anterior es solo una sugerencia que su programa hace al sistema operativo.

En cuanto a Go, aún no he trabajado con él ni lo he examinado demasiado, pero mi opinión sobre Go es que gran parte del paralelismo es bastante implícito. Tienes co-rutinas (dicen "go-rutines", muy punny) y comunicación entre ellas. Parece que la afinidad de la CPU y el concepto de enhebrar a sí mismo están separados de eso. Es decir, el tiempo de ejecución del lenguaje incluso podría decidir hacer todo en una CPU si decide que es mejor ... Pero, de nuevo, advierto que no lo he examinado demasiado profundamente, así que podría estar equivocado. :-)

2

La respuesta es sí, se puede elegir mediante programación núcleo que se ejecuta en un proceso. Como mencionó arsane, la respuesta está en sched_set_affinity(), y luego pthread_setaffinity_np() para pthreads.

Aquí es una nifty tutorial sobre cómo hacer esto con los procesos (que proviene de una respuesta a la pregunta this.)

Básicamente, esto se hace usando una máscara de bits. Esto significa que hay un entero (por ejemplo, 32 bits), y si el primer bit == 1, ese proceso puede ejecutarse en el procesador 1. Si el segundo bit == 1, se permite que ese proceso se ejecute en procesador 2. etc.

De forma predeterminada, la máscara de bits de afinidad = 1 ... 111 (32 veces). Esto significa que "El proceso puede ejecutarse en el procesador 1, 2, 3, ..., 32." Por supuesto, si solo tiene 2 núcleos, entonces los 30 bits adicionales no se aplicarán.

Sin embargo, si establece que la máscara de bits sea: 0 ... 010, solo el "procesador 2" podrá ejecutar ese proceso.

Lo que también explica por qué el maximum number de procesadores compatibles con Linux es 32. (de fábrica, sin ajustes, x86, en gran parte del hardware común, sin agrupamiento, etc.).

Cuestiones relacionadas