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: 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:
- Múltiples conjuntos de registros: cada hilo de hardware tiene su propio PC, SP, registros generales y registros de control.
- Recursos compartidos: ALU, FPU, caché L1/L2, TLB, bus de memoria.
- Planificador de hardware: decide qué instrucciones de qué hilo ejecutar en cada ciclo.
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:
- Procesos que compiten por los mismos recursos: si dos procesos intensivos en CPU se ejecutan en el mismo núcleo físico (SMT), compiten por la ALU y la caché, y el rendimiento de ambos baja.
- Procesos complementarios: si un proceso es intensivo en CPU y otro es intensivo en memoria, se ejecutan bien juntos en SMT porque usan recursos diferentes.
- Balanceo: el planificador debe considerar que dos hilos de hardware de un mismo núcleo no son tan independientes como dos núcleos físicos.
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.
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:
- Nodos: cada socket (o grupo de procesadores) tiene un nodo NUMA con su propia memoria.
- Memoria local: la memoria conectada al socket del procesador que la accede. Acceso rápido (típicamente 100 ns).
- Memoria remota: la memoria conectada a otro socket. Acceso más lento (típicamente 200-300 ns, dependiendo de la distancia).
- Interconexión: los nodos se conectan mediante un bus o red de interconexión (QPI, UPI en Intel; Infinity Fabric en AMD).
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:
- Asignación de memoria: cuando un proceso se crea, se asigna memoria en un nodo. Si el proceso se migra a otro nodo, sus accesos a memoria serán remotos.
- Balanceo vs localidad: migrar un proceso para balancear la carga puede empeorar la localidad de memoria.
- Políticas de asignación: el sistema puede asignar memoria en el nodo local (first-touch), en un nodo específico, o de forma intercalada (interleaving).
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:
- Un conjunto de CPUs: los CPUs que pertenecen al dominio.
- Un dominio padre: el dominio de nivel superior.
- Parámetros de balanceo: intervalo, umbral, etc.
- Flags: indican si el balanceo está habilitado, si hay SMT, etc.
8. La jerarquía de dominios
La jerarquía típica de dominios en un sistema multi-socket es:
| Nivel | Dominio | CPUs | Costo de migración |
|---|---|---|---|
| 0 | Hilos SMT | 2 hilos del mismo núcleo | Muy bajo (comparten caché L1/L2) |
| 1 | Núcleo | Núcleos del mismo socket | Bajo (comparten caché L3) |
| 2 | Socket | Sockets del mismo nodo NUMA | Medio (sin caché compartida) |
| 3 | Nodo NUMA | Nodos NUMA del sistema | Alto (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/:
$ 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:
- numactl: controla la asignación de memoria y la afinidad de CPU.
- numastat: muestra estadísticas de acceso a memoria NUMA.
- taskset: fija un proceso a un CPU específico.
$ 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
| Herramienta | Qué muestra | Cómo usarla |
|---|---|---|
lscpu | Topologí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 --hardware | Nodos NUMA y sus CPUs. | numactl --hardware |
numastat | Estadísticas de acceso NUMA. | numastat |
perf stat | Contadores 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)
| Proceso | Ráfaga | CPU | Socket | Inicio | Fin | Retorno |
|---|---|---|---|---|---|---|
12. Resumen
- SMT permite a un núcleo ejecutar varios hilos simultáneamente, compartiendo recursos.
- El rendimiento de SMT es ~1,2-1,3×, no 2×.
- NUMA: la memoria no es uniforme; el acceso local es más rápido que el remoto.
- Los dominios de planificación organizan los CPUs en jerarquía para balancear eficientemente.
- La jerarquía es: SMT → núcleo → socket → nodo NUMA.
- Linux balancea primero en los dominios más bajos (menor costo).
- Las herramientas numactl, numastat y taskset permiten observar y controlar el comportamiento.
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
- Ejecuta lscpu en tu sistema y analiza la topología.
- Ejecuta numastat y analiza los accesos locales y remotos.
- Usa taskset para fijar un proceso a un CPU y observa el rendimiento.
- Explica por qué SMT no duplica el rendimiento.
- Investiga cómo numactl controla la asignación de memoria.
- Explica por qué la jerarquía de dominios reduce el costo del balanceo.