← Planificación de la CPU Bloque 8 · Planificación en multiprocesadores · Tema 30 de 44

Tema 30

Hilos de hardware, NUMA y dominios

Los procesadores modernos no son simples: tienen hilos de hardware (SMT/Hyper-Threading) que comparten recursos, y sistemas NUMA donde la memoria no es uniforme. Estos factores complican la planificación: no todos los «procesadores» son iguales, y no toda la memoria es igual de rápida. En este tema verás SMT, NUMA y cómo Linux organiza los CPUs en dominios de planificación para manejar esta complejidad.

1. Hilos de hardware (SMT)

SMT (Simultaneous Multi-Threading) es una técnica de hardware que permite a un solo núcleo físico ejecutar dos (o más) hilos de hardware simultáneamente. Intel lo llama Hyper-Threading, AMD lo llama SMT. Cada hilo de hardware aparece al sistema operativo como un procesador lógico independiente.

Un núcleo con SMT tiene dos (o más) conjuntos de registros (PC, SP, registros generales) pero comparte los recursos de ejecución (ALU, FPU, caché, bus de memoria). Los dos hilos se ejecutan simultáneamente, compartiendo los recursos.

La idea es que si un hilo está esperando memoria (cache miss), el otro hilo puede usar los recursos de ejecución que están ociosos. Así, el núcleo se aprovecha mejor.

SMT no duplica el núcleo

SMT no duplica el núcleo: comparte los recursos de ejecución. El rendimiento de dos hilos en un núcleo con SMT es típicamente 1,2-1,3 veces el de un solo hilo, no 2 veces. Si ambos hilos usan los mismos recursos (por ejemplo, la FPU), el rendimiento puede ser incluso peor que ejecutarlos secuencialmente.

2. Cómo funciona SMT

El núcleo físico tiene:

El planificador de hardware intercala instrucciones de los dos hilos en cada ciclo. Si un hilo tiene un cache miss, el otro hilo puede usar los recursos de ejecución mientras el primero espera.

El sistema operativo no necesita saber que SMT existe: ve dos procesadores lógicos y los planifica independientemente. Pero el planificador del SO puede optimizar para SMT: por ejemplo, no ejecutar dos procesos intensivos en CPU en el mismo núcleo físico (porque competirían por los mismos recursos).

3. SMT y planificación

SMT introduce nuevos desafíos para el planificador:

Linux tiene soporte para SMT: el planificador intenta no ejecutar dos procesos intensivos en CPU en el mismo núcleo físico. También proporciona información sobre la topología (qué hilos de hardware comparten un núcleo físico) a través de /sys/devices/system/cpu/.

4. NUMA: memoria no uniforme

NUMA (Non-Uniform Memory Access) es una arquitectura de memoria en la que el tiempo de acceso a la memoria depende de la ubicación física del procesador y de la memoria. Un procesador accede más rápido a la memoria local (conectada a su socket) que a la memoria remota (conectada a otro socket).

En un sistema SMP tradicional (UMA, Uniform Memory Access), todos los procesadores acceden a la memoria con el mismo tiempo. En NUMA, la memoria se divide en nodos, cada uno asociado a un socket (o grupo de procesadores). Un procesador accede a su nodo local rápidamente y a los nodos remotos más lentamente.

NUMA es la arquitectura estándar en servidores multi-socket. Un servidor con 2 sockets tiene 2 nodos NUMA, cada uno con su propia memoria. Un servidor con 4 sockets tiene 4 nodos NUMA.

NUMA no es opcional en servidores

En servidores multi-socket, NUMA es inevitable: la memoria se conecta físicamente a cada socket. El sistema operativo debe manejar la no-uniformidad para obtener buen rendimiento.

5. Cómo funciona NUMA

En un sistema NUMA:

El sistema operativo debe asignar memoria al nodo del procesador que la va a usar, para minimizar los accesos remotos. Si un proceso se ejecuta en el nodo 0, su memoria debería estar en el nodo 0.

6. NUMA y planificación

NUMA introduce nuevos desafíos para el planificador:

Linux tiene soporte para NUMA: el planificador intenta mantener un proceso en el mismo nodo (afinidad NUMA) y asignar memoria en el nodo local. Las herramientas numactl y numastat permiten controlar y observar el comportamiento NUMA.

7. Dominios de planificación

Los dominios de planificación (scheduling domains) son la estructura que Linux usa para organizar los CPUs en grupos jerárquicos y balancear la carga de forma eficiente. Cada dominio representa un nivel de la jerarquía de hardware: hilos SMT, núcleos, sockets, nodos NUMA.

Los dominios permiten al planificador tomar decisiones informadas sobre migración: primero intenta balancear dentro del mismo dominio (bajo costo), y solo si es necesario migra a un dominio superior (mayor costo).

Cada dominio tiene:

8. La jerarquía de dominios

La jerarquía típica de dominios en un sistema multi-socket es:

NivelDominioCPUsCosto de migración
0Hilos SMT2 hilos del mismo núcleoMuy bajo (comparten caché L1/L2)
1NúcleoNúcleos del mismo socketBajo (comparten caché L3)
2SocketSockets del mismo nodo NUMAMedio (sin caché compartida)
3Nodo NUMANodos NUMA del sistemaAlto (memoria remota)

El planificador balancea primero en el nivel más bajo (SMT), luego en el núcleo, luego en el socket, y finalmente entre nodos NUMA. Esto minimiza el costo de las migraciones: la mayoría son locales.

9. Cómo lo hace Linux

Linux expone la topología del hardware a través de /sys/devices/system/cpu/ y /sys/devices/system/node/:

terminal · ver la topología
$ lscpu
Architecture:        x86_64
CPU(s):              16
Thread(s) per core:  2
Core(s) per socket:  8
Socket(s):           1
NUMA node(s):        1
$ cat /sys/devices/system/cpu/cpu0/topology/thread_siblings_list
0,8
$ ls /sys/devices/system/node/
node0  has_cpu  has_memory  has_normal_memory

Linux también proporciona herramientas para observar y controlar el comportamiento NUMA:

terminal · numastat
$ numastat
                           node0
numa_hit                  1234567
numa_miss                     123
numa_foreign                    0
interleave_hit                  0
local_node                  1234567
other_node                    123

numa_miss indica los accesos a memoria remota. Un valor alto indica que el planificador no está asignando memoria correctamente.

10. Herramientas de observación

HerramientaQué muestraCómo usarla
lscpuTopología: sockets, núcleos, hilos, nodos NUMA.lscpu
/sys/devices/system/cpu/Topología detallada de cada CPU.cat /sys/devices/system/cpu/cpu0/topology/*
numactl --hardwareNodos NUMA y sus CPUs.numactl --hardware
numastatEstadísticas de acceso NUMA.numastat
perf statContadores de hardware (cache misses, etc.).perf stat -e cache-misses ./programa

11. Simulador interactivo

Este simulador muestra cómo la jerarquía de dominios afecta al balanceo. Con 4 CPUs en 2 sockets (2 por socket), el balanceo se hace primero dentro del socket:

Simulador · dominios de planificación

Socket 0 (CPU 0, 1)

Socket 1 (CPU 2, 3)

ProcesoRáfagaCPUSocketInicioFinRetorno

12. Resumen

13. Preguntas de repaso

Intenta responder cada una antes de abrir la respuesta.

1. ¿Qué es SMT?

Simultaneous Multi-Threading: un núcleo físico ejecuta varios hilos de hardware simultáneamente, compartiendo recursos.

2. ¿Cuánto mejora el rendimiento SMT?

Típicamente 1,2-1,3×, no 2×. Depende de si los hilos usan los mismos recursos.

3. ¿Qué es NUMA?

Non-Uniform Memory Access: el tiempo de acceso a la memoria depende de la ubicación física del procesador y la memoria.

4. ¿Cuál es la diferencia entre memoria local y remota en NUMA?

La memoria local (mismo nodo) es más rápida; la remota (otro nodo) es más lenta.

5. ¿Qué son los dominios de planificación?

Grupos de CPUs organizados en jerarquía para balancear la carga eficientemente.

6. ¿Cuál es la jerarquía típica de dominios?

SMT → núcleo → socket → nodo NUMA.

7. ¿Por qué se balancea primero en los dominios más bajos?

Porque tienen menor costo de migración (comparten caché).

8. ¿Qué herramienta muestra la topología NUMA?

numactl --hardware y lscpu.

9. ¿Qué indica un numa_miss alto?

Que hay muchos accesos a memoria remota, indicando mala asignación.

10. ¿Cómo se fija un proceso a un CPU en Linux?

Con taskset o sched_setaffinity.

Para practicar

  1. Ejecuta lscpu en tu sistema y analiza la topología.
  2. Ejecuta numastat y analiza los accesos locales y remotos.
  3. Usa taskset para fijar un proceso a un CPU y observa el rendimiento.
  4. Explica por qué SMT no duplica el rendimiento.
  5. Investiga cómo numactl controla la asignación de memoria.
  6. Explica por qué la jerarquía de dominios reduce el costo del balanceo.