El ticket siempre empieza igual: “Habilitamos la función de IA y ahora los portátiles se calientan, los ventiladores chillan
y la cola de helpdesk parece un ataque de denegación de servicio”. Alguien sugiere “simplemente usad la CPU, está bien.”
Otra persona propone comprar GPUs para todo el mundo, que es como convertir una petición modesta en una audiencia presupuestaria.
Las NPUs existen porque ambos instintos suelen estar equivocados en producción. Las CPU pueden ejecutar IA, sí. También pueden tostar pan.
Eso no significa que quieras tenerlas como tostadora todo el día mientras también son tu hoja de cálculo, tu videollamada y tu agente de seguridad.
NPUs, en términos sencillos: qué son (y qué no son)
Una NPU (Unidad de Procesamiento Neuronal) es un acelerador especializado diseñado para ejecutar eficientemente las matemáticas de redes neuronales:
muchas operaciones de multiplicar-acumular, álgebra lineal densa y los patrones de movimiento de datos que las acompañan.
El objetivo operativo no es “lo más rápido posible sin importar qué”. Es “lo suficientemente rápido con muy bajo consumo, latencia predecible
y sin acaparar toda la máquina”.
En sistemas cliente modernos (portátiles, tabletas, teléfonos), una NPU suele estar integrada en el chip o en el paquete con la CPU,
a menudo compartiendo memoria y el interconector/fabric. En servidores, verás más a menudo aceleradores discretos (GPUs, TPUs,
tarjetas de inferencia) porque el presupuesto de potencia y refrigeración es mayor y las cargas son más pesadas. Pero la lógica es la misma:
mover el cálculo correcto al motor correcto.
Qué no es una NPU:
- No es un reemplazo de una GPU si entrenas modelos grandes o haces inferencia por lotes a escala.
- No es magia si tu cuello de botella es el ancho de banda de memoria, E/S de disco o una canalización lenta de pre/postprocesado.
- No es automáticamente más rápida para todos los modelos; la cobertura de operadores, la cuantización y el soporte del framework deciden el resultado.
Por qué existen las NPUs: las limitaciones que las CPU no pueden evitar
Una CPU es un generalista. Está diseñada para hacer un millón de cosas de forma aceptable: código con muchas ramas, trabajo del SO, cifrado,
redes, lógica de negocio variada, todos los pequeños bordes que hacen que el software sea “real”. También está construida alrededor de
acceso de baja latencia a cachés, amplia especulación y lógica de control sofisticada. Eso es caro en silicio y en energía.
La inferencia de redes neuronales, en contraste, suele estar dominada por:
- Multiplicaciones de matrices (GEMM) y operaciones tipo convolución.
- Alta intensidad aritmética cuando hay buen reuso de datos, pero presión sobre el ancho de banda de memoria cuando no lo hay.
- Cálculo de baja precisión (INT8, FP16, BF16) que las CPU pueden realizar, pero no tan eficientemente por vatio como un motor dedicado.
Las NPUs existen porque el “modelo de costes” para la IA en cliente es brutal:
- Potencia: La gente nota la drenación de batería y el ruido del ventilador de inmediato. La factura de la nube es otro tipo de dolor; los usuarios no la oyen.
- Térmicas: La inferencia sostenida en la CPU puede provocar throttling, y entonces todo lo demás también se degrada.
- Latencia: Las funciones en dispositivo (desenfoque de fondo, transcripción, wake-word, mejora de imágenes) necesitan latencia baja y estable.
- Concurrencia: La CPU también debe ejecutar el SO, el navegador, el agente EDR y cualquier otro proceso que la empresa arranque automáticamente.
Si alguna vez has visto un portátil intentando transcribir audio en la CPU mientras ejecuta una videollamada, has visto esta película.
El giro argumental siempre es el mismo: la función de IA es “solo 10 ms por fotograma” en el laboratorio, pero en campo se convierte
en “picos aleatorios de 200 ms y la reunión se vuelve una presentación de diapositivas”.
Chequeo de realidad “IA en la CPU”: lo que realmente ocurre
Sí, las CPU pueden ejecutar inferencia. Los núcleos x86 y ARM modernos tienen extensiones vectoriales (AVX2/AVX-512 en x86; NEON/SVE en ARM),
y existen bibliotecas optimizadas (oneDNN, variantes BLAS, kernels de proveedores) que hacen un trabajo respetable.
Pero “respetable” no es lo mismo que “barato y predecible”.
En producción, la inferencia en CPU falla de formas repetibles:
1) Te topas con la pared de memoria, no con la de cómputo
Muchas cargas de inferencia están efectivamente limitadas por el ancho de banda de memoria, especialmente cuando los pesos no caben en caché.
Puedes tener mucho cómputo vectorial disponible y aun así estar constantemente esperando datos.
Cuando la CPU está bloqueada, consume energía sin hacer mucho, y tu latencia se vuelve variable.
2) Luchas con el planificador
Las CPU hacen time-slice. Ese es el punto. Pero para funciones real-time-ish de IA, la preempción y la contención importan.
El SO, servicios en segundo plano y otras apps interrumpirán tus hilos de inferencia.
Si “optimizas” fijando núcleos o aumentando el conteo de hilos, puede que ganes una métrica y pierdas la experiencia del usuario.
3) Las elecciones de precisión se vuelven decisiones de producto
La inferencia en CPU suele necesitar cuantización (INT8, a veces INT4) para ser competitiva.
La cuantización no es solo una perilla de rendimiento; afecta la precisión del modelo, la estabilidad de las salidas y el comportamiento en casos límite.
En un entorno empresarial, “la precisión empeoró para ciertos acentos” se convierte en un problema de cumplimiento y recursos humanos, no en una nota técnica.
4) Pagas un impuesto de integración
Hacer que “IA en la CPU” rinda significa elegir el runtime correcto, los kernels correctos, la configuración de hilos adecuada
y el formato de modelo correcto. Se puede hacer. Pero es trabajo. Las NPUs existen para reducir el coste de hacer eso repetidamente
a través de una flota.
Una regla seca que se cumple: si el modelo funciona “bien” en la estación de trabajo del desarrollador, espera que funcione “picoso” en el portátil medio.
Tu portátil medio es donde la felicidad va a morir.
Dentro de la caja: cómo se construyen las NPUs de forma distinta
A alto nivel, una NPU es una cinta transportadora construida para operaciones tensoriales. Los detalles varían según el proveedor, pero los temas son consistentes:
Flujo de datos en lugar de especulación
Las CPU ganan en flujo de control impredecible. Las NPUs asumen lo contrario: el grafo de cómputo es conocido, las operaciones se repiten,
y lo mejor que puedes hacer es mantener los datos moviéndose por las unidades MAC con una sobrecarga de control mínima.
Menos predicción de ramas, menos complejidad out-of-order, más rendimiento sostenido.
Memoria local y tiling como ciudadanos de primera clase
Las NPUs típicamente tienen memorias locales tipo SRAM (scratchpads) que el compilador/runtime gestionan explícitamente.
Eso no es un accidente; es cómo evitas tocar DRAM en cada reuso de pesos/activaciones.
El runtime corta tensores en mosaicos que caben localmente, hace un trozo de trabajo y sigue.
La baja precisión es la predeterminada
Las NPUs funcionan mejor cuando les das INT8/INT16/FP16/BF16 y operaciones que reconocen.
A menudo tienen instrucciones dedicadas para operaciones fusionadas (por ejemplo, convolución + activación, o GEMM + bias + activación),
porque fusionar ahorra ancho de banda y reduce viajes de ida y vuelta a memoria.
La latencia predecible es un requisito de producto
En dispositivos cliente, la “sensación” importa más que el rendimiento pico. Eso impulsa decisiones de diseño:
colas acotadas, planificadores hardware y aislamiento para que la NPU pueda ejecutar IA en segundo plano sin robarle el almuerzo a la CPU.
Un modelo mental útil: las CPU están diseñadas alrededor del control. Las GPU están diseñadas alrededor del throughput.
Las NPUs están diseñadas alrededor del throughput por vatio con memoria gestionada por compilador.
NPU vs GPU vs CPU: elige tu veneno
Si tienes que decidir dónde ejecutar la inferencia, usa este marco: ¿qué optimizas—coste, latencia, potencia o tiempo de ingeniería?
La respuesta equivocada es “lo que esté disponible”. Así es como terminas con una CPU haciendo el 80% del trabajo mientras la NPU espera
pacientemente a que dejes de ser creativo.
CPU: mejor para pegamento, modelos pequeños y “debe ejecutarse en todas partes”
- Pros: disponibilidad universal; excelente en pre/postprocesado; depuración sencilla; herramientas maduras.
- Contras: limitaciones de potencia/térmicas; latencia variable bajo carga; a menudo limitado por memoria; aumentar hilos puede perjudicar.
- Usar cuando: el modelo es pequeño, el ciclo de trabajo es bajo o la portabilidad importa más que la eficiencia pico.
GPU: mejor para gran throughput y entrenamiento (y muchos casos de inferencia)
- Pros: paralelismo masivo; ecosistema maduro; buen soporte para FP16/BF16; excelente throughput por batching.
- Contras: consumo de potencia; GPUs discretas añaden coste/compljidad; tareas pequeñas en tiempo real sufren overhead de lanzamiento/planificación.
- Usar cuando: tienes modelos grandes, necesidades de alto throughput o entrenamiento. O ya estás en GPU-land y operativamente es barato.
NPU: mejor para inferencia en dispositivo con presupuestos estrictos de potencia y latencia
- Pros: excelente perf/W; puede ejecutar tareas always-on; aísla el trabajo de IA de la CPU; bueno para privacidad (sin viaje a la nube).
- Contras: lagunas en cobertura de operadores; herramientas variadas; conversión de modelos puede ser dolorosa; riesgo de vendor lock-in.
- Usar cuando: distribuyes funciones cliente a una flota y necesitas batería/térmicas predecibles y experiencia de usuario consistente.
Exactamente una broma, como prometí: Una NPU es como una carretilla elevadora—genial moviendo palés, terrible escribiendo correos, y aun así de algún modo culpada por ambos.
Datos interesantes y breve historia
Diez datos breves para calibrar tus instintos. No son trivialidades; explican por qué el ecosistema es como es.
- Los aceleradores neuronales no son nuevos. DSPs y ASICs tempranos de inferencia existían mucho antes de que “NPU” fuera un término de marketing; simplemente no eran tendencia.
- El móvil impulsó las primeras NPUs. Los teléfonos necesitaban visión y voz en dispositivo sin freír la batería, empujando a los proveedores hacia bloques dedicados.
- La cuantización se popularizó por la potencia. INT8 no se adoptó porque a los ingenieros les guste la baja precisión; se adoptó porque las baterías lo requieren.
- Los tensor cores cambiaron expectativas. Las unidades tensoriales de GPU popularizaron la mezcla de precisión y convirtieron “matemáticas matriciales especializadas” en una parte por defecto de la planificación de IA.
- Las pilas de compilador se volvieron estratégicas. Para NPUs, el compilador y el optimizador de grafos pueden importar tanto como el silicio. A veces más.
- La cobertura de operadores es una limitación real. Si la NPU no soporta una operación o patrón de fusión, vuelves a CPU/GPU y el rendimiento colapsa.
- El marketing de “TOPS” oculta lo difícil. Los números pico de tera-ops suelen asumir kernels ideales, tiling perfecto y cero penalizaciones por movimiento de datos. La realidad te factura por la memoria.
- La IA en dispositivo es también una historia de privacidad. Mantener audio/video local reduce la exposición de datos y la carga legal, algo que las empresas aprecian en silencio.
- Windows y Linux están poniéndose al día de forma desigual. Algunas NPUs tienen integración de primer nivel con el SO; otras parecen un proyecto de feria de ciencias pegado a un driver.
- La inferencia en el edge cada vez trata más de orquestación. El “acelerador” no es solo un chip; es formato de modelo, runtime, planificación, política de energía y observabilidad.
Guión de diagnóstico rápido: identifica el cuello de botella con rapidez
Cuando una función de IA “va lenta”, tienes quizá 20 minutos antes de que la gente empiece a sugerir reescribirlo en Rust.
Aquí tienes un guión que funciona en portátiles, estaciones de desarrollo y cajas edge.
Primero: confirma dónde se está ejecutando realmente la inferencia
- Objetivo: ¿Se ejecuta el modelo en CPU, GPU, NPU—o salta entre ellos?
- Por qué: La ejecución mixta a menudo parece “usa el acelerador” mientras sigue estando limitada por la CPU en operaciones no soportadas.
Segundo: decide si estás limitado por cómputo o por memoria
- Objetivo: ¿Los cores están ocupados haciendo cálculo, o están bloqueados por memoria y fallos de caché?
- Por qué: Si estás limitado por memoria, “más hilos” es gasolina en un incendio de basura.
Tercero: comprueba throttling térmico y de potencia
- Objetivo: ¿El sistema reduce frecuencia bajo carga sostenida?
- Por qué: El throttling convierte tus gráficas de rendimiento en arte moderno: picudas y difíciles de justificar.
Cuarto: perfila la canalización, no solo el modelo
- Objetivo: Mide decodificación, redimensionado, extracción de características, tokenización y postprocesado.
- Por qué: Es común que “el modelo” sea solo la mitad de la latencia; el resto es tu código de pegamento y E/S.
Quinto: valida la cobertura de operadores / tasa de fallback
- Objetivo: Identifica qué ops no están soportadas en la NPU y dónde ocurre la devolución.
- Por qué: Una operación no soportada en el lugar equivocado puede forzar un bucle de copias dispositivo-host que destruye rendimiento y energía.
Una cita operativa para mantener la honestidad, parafraseada porque la precisión importa: paraphrased idea
— Gene Kranz:
“Duro y competente” vence a “ingenioso” cuando los sistemas están bajo presión.
Tareas prácticas: comandos, salidas y decisiones (12+)
Estas tareas están diseñadas para el mundo real: tienes una máquina, un runtime de modelo y una queja.
Cada tarea incluye un comando, una salida de ejemplo, qué significa la salida y qué decisión tomar a continuación.
Los comandos se orientan a Linux porque ahí puedes ver los engranajes. Si estás en Windows/macOS, los principios siguen aplicando.
Task 1: Identify CPU features relevant to inference (AVX/AVX-512, etc.)
cr0x@server:~$ lscpu | egrep -i 'Model name|Socket|Thread|Core|Flags'
Model name: Intel(R) Xeon(R) Silver 4314 CPU @ 2.40GHz
Socket(s): 2
Core(s) per socket: 16
Thread(s) per core: 2
Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr ... avx2 avx512f avx512bw avx512vl ...
Meaning: You have AVX2 and AVX-512. Many CPU inference libraries will select different kernels based on these flags.
Decision: If AVX-512 is absent on a target fleet, don’t benchmark only on a dev Xeon and declare victory. Build baselines on representative hardware.
Task 2: Check whether the kernel sees an NPU-like accelerator device
cr0x@server:~$ lspci -nn | egrep -i 'neural|npu|vpu|accelerator|inference'
00:0b.0 Processing accelerators [1200]: Intel Corporation Device [8086:7d1d] (rev 01)
Meaning: The PCI layer sees a “processing accelerator.” That’s a start, not proof it’s usable.
Decision: Proceed to driver and runtime checks. If nothing appears, you may be in “integrated device exposed differently” territory, or you simply don’t have an NPU.
Task 3: Confirm the driver is loaded (and not silently failing)
cr0x@server:~$ lsmod | egrep -i 'vpu|npu|accel|ivpu|amdxdna'
ivpu 151552 0
accel_core 32768 1 ivpu
Meaning: Kernel modules are present. This reduces the chance you’re stuck in CPU fallback due to missing drivers.
Decision: If modules aren’t loaded, check dmesg for firmware and initialization errors before blaming the runtime.
Task 4: Read dmesg for accelerator initialization and firmware issues
cr0x@server:~$ dmesg -T | egrep -i 'ivpu|npu|vpu|firmware|accel' | tail -n 20
[Mon Jan 12 09:02:11 2026] ivpu 0000:00:0b.0: enabling device (0000 -> 0002)
[Mon Jan 12 09:02:11 2026] ivpu 0000:00:0b.0: loading firmware intel/vpu/vpu_37xx.bin
[Mon Jan 12 09:02:12 2026] ivpu 0000:00:0b.0: initialized successfully
Meaning: Firmware loaded and the device initialized. If you see repeated resets or “failed to load firmware,” expect performance to be “CPU-only.”
Decision: Fix firmware/driver first. Model tuning won’t help if the accelerator isn’t operational.
Task 5: Confirm CPU frequency scaling and detect throttling risk
cr0x@server:~$ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
powersave
Meaning: You’re in powersave. Great for battery; possibly terrible for latency benchmarks.
Decision: For controlled tests, switch to performance. For production, keep power policies but measure within them.
Task 6: Change governor for a benchmark run (controlled testing only)
cr0x@server:~$ sudo bash -lc 'for c in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do echo performance > $c; done'
cr0x@server:~$ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
performance
Meaning: You’ve reduced frequency scaling variance.
Decision: If performance improves drastically, your “AI is slow” problem may be power policy, not architecture. Decide whether you can request higher QoS for the workload.
Task 7: Measure CPU saturation and scheduler pressure during inference
cr0x@server:~$ mpstat -P ALL 1 5
Linux 6.8.0 (server) 01/12/2026 _x86_64_ (64 CPU)
09:10:01 AM CPU %usr %nice %sys %iowait %irq %soft %steal %idle
09:10:02 AM all 78.12 0.00 3.10 0.02 0.00 0.55 0.00 18.21
09:10:02 AM 12 99.00 0.00 0.80 0.00 0.00 0.20 0.00 0.00
09:10:02 AM 13 98.50 0.00 1.00 0.00 0.00 0.50 0.00 0.00
Meaning: A couple of cores are pegged; overall CPU is high. That suggests either single-stream compute bound or thread pinning.
Decision: If latency matters, consider fewer threads with better cache locality, or move the hot path to NPU/GPU if supported.
Task 8: Detect memory pressure and swapping (silent inference killer)
cr0x@server:~$ free -h
total used free shared buff/cache available
Mem: 31Gi 27Gi 1.2Gi 196Mi 3.0Gi 2.1Gi
Swap: 8.0Gi 3.4Gi 4.6Gi
Meaning: Swap is in use. That’s a red flag for inference latency and jitter.
Decision: Reduce model size, use quantization, or enforce memory limits. If you must run locally, avoid swapping at all costs.
Task 9: Confirm whether you’re I/O bound due to model loading
cr0x@server:~$ iostat -xz 1 3
Linux 6.8.0 (server) 01/12/2026 _x86_64_ (64 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
42.10 0.00 2.80 18.60 0.00 36.50
Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz w/s wkB/s w_await aqu-sz %util
nvme0n1 320.0 86000.0 0.0 0.00 12.40 268.8 10.0 512.0 1.20 4.10 92.00
Meaning: High disk utilization and iowait during runs. You may be timing model load and page faults, not compute.
Decision: Warm the model into memory, use memory-mapped weights carefully, and separate “startup latency” from “steady-state inference latency.”
Task 10: Check NUMA topology (server inference often trips here)
cr0x@server:~$ numactl -H
available: 2 nodes (0-1)
node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
node 0 size: 128790 MB
node 0 free: 12410 MB
node 1 cpus: 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
node 1 size: 128733 MB
node 1 free: 80210 MB
Meaning: Memory is unevenly free across NUMA nodes. If your process runs on node 0 but allocates memory on node 1, latency goes sideways.
Decision: Pin the process and its memory allocations to the same NUMA node for repeatable results, especially for CPU inference.
Task 11: Run with NUMA pinning to reduce remote memory access (benchmark)
cr0x@server:~$ numactl --cpunodebind=0 --membind=0 ./inference_bench --model ./models/model.int8.onnx --threads 16
model_load_ms=420
p50_latency_ms=18.2
p95_latency_ms=23.9
throughput_qps=54.1
Meaning: Improved tail latency typically indicates you were paying remote NUMA penalties before.
Decision: If you can’t pin in production, at least detect NUMA and avoid pathological placements in your service manager configuration.
Task 12: Confirm which shared libraries you’re actually using (kernel selection matters)
cr0x@server:~$ ldd ./inference_bench | egrep -i 'onnx|dnn|mkl|openvino|cuda|tensorrt'
libonnxruntime.so.1 => /usr/local/lib/libonnxruntime.so.1 (0x00007f8c1c000000)
libmkl_rt.so.2 => /opt/intel/oneapi/mkl/latest/lib/intel64/libmkl_rt.so.2 (0x00007f8c17000000)
Meaning: You’re using MKL-backed kernels (good for CPU). If you expected an NPU execution provider, it’s not here.
Decision: Fix runtime configuration. Don’t benchmark “CPU only” and call it “NPU slow.”
Task 13: Trace context switches and migrations (jitter source)
cr0x@server:~$ pidof inference_bench
24817
cr0x@server:~$ sudo perf sched record -p 24817 -- sleep 10
cr0x@server:~$ sudo perf sched latency | head
Task | Runtime ms | Switches | Average delay ms | Maximum delay ms
inference_bench:24817 | 9521.330 | 8212 | 0.141 | 7.882
Meaning: Many switches and some non-trivial max delay. For real-time-ish inference, those spikes show up as user-visible stutter.
Decision: Consider reducing thread count, setting CPU affinity, or moving the workload off CPU if you need consistent latency.
Task 14: Watch power/thermal throttling signals (on systems that expose them)
cr0x@server:~$ sudo turbostat --Summary --quiet --interval 2 --num_iterations 3
CPU Avg_MHz Busy% Bzy_MHz TSC_MHz PkgTmp PkgWatt
- 1890 72.15 2620 2400 92 54.30
- 1710 74.02 2310 2400 96 55.10
- 1605 76.40 2100 2400 99 55.40
Meaning: Temperature climbs and effective MHz drops. That’s throttling behavior in the making (or already happening).
Decision: If you need sustained inference, an NPU (or a properly cooled GPU) is a better fit. Otherwise lower duty cycle, reduce model size, or accept lower quality.
Task 15: Confirm cgroup CPU limits (containers love to surprise you)
cr0x@server:~$ cat /sys/fs/cgroup/cpu.max
200000 100000
Meaning: The process is capped to 2 CPUs worth of time. Your “why is it slow” may be “because you told it to be slow.”
Decision: Adjust CPU limits, or size the model to the quota. Also: stop comparing container benchmarks to bare-metal numbers without acknowledging the cap.
Task 16: Check hugepages and THP status (can affect large weight access patterns)
cr0x@server:~$ cat /sys/kernel/mm/transparent_hugepage/enabled
always [madvise] never
Meaning: THP is in madvise mode. Whether that helps depends on the allocator and access pattern.
Decision: If you see page fault overhead and TLB misses in profiling, experiment with THP settings in a controlled test. Don’t flip it fleet-wide as a “performance fix” without evidence.
Tres micro-historias corporativas desde el terreno
Mini-historia 1: El incidente causado por una suposición equivocada
Una empresa mediana desplegó una función de “resumen en dispositivo” para notas de reuniones internas. Los arquitectos habían hecho los cálculos:
el modelo estaba cuantizado, la inferencia en CPU parecía aceptable en un laboratorio tranquilo, y la NPU “estaba para más adelante.”
El plan de despliegue asumía que “la CPU siempre está disponible” significaba “la CPU siempre está disponible para esto”.
Dos días después del lanzamiento, los tickets de soporte se dispararon. Los usuarios se quejaban de que las videollamadas se entrecortaban y sus máquinas se calentaban.
IT notó algo peor: los escaneos de protección de endpoints estaban expirando, porque la CPU permanecía ocupada el tiempo suficiente como para que otros agentes
perdieran sus ventanas. Nada se colapsó, pero todo empeoró a la vez—el clásico incidente de degradación lenta.
La suposición equivocada fue sutil: el equipo midió la latencia media por inferencia, no el ciclo de trabajo.
En producción, la función se ejecutó continuamente en segundo plano para “mantenerse lista”. La utilización de CPU se volvió sostenida,
el sobre de térmicas se llenó, la CPU redujo frecuencia y la latencia pico para todo lo demás creció de forma no lineal.
La solución fue operativa, no heroica. Movieron la parte always-on (extracción de características y embeddings pequeños)
a la NPU donde fue soportado, y cambiaron el comportamiento del producto: los resúmenes se generaban bajo demanda,
no se precomputaban continuamente. También añadieron una regla de “retroceso bajo carga” basada en temperatura de CPU y métricas de retraso del planificador.
La lección clave: si tu función de IA es continua, trátala como un daemon. Los daemons necesitan presupuestos, no optimismo.
Mini-historia 2: La optimización que salió mal
Otra empresa lanzó un appliance edge que hacía detección de anomalías en tiempo real sobre flujos de vídeo.
Un ingeniero de rendimiento observó que los bloques de convolución del modelo eran amigables con la NPU, pero el preprocesado estaba en la CPU.
Decidieron “optimizar” moviendo el preprocesado a una ruta de shader GPU personalizada en sistemas con GPUs discretas,
mientras la inferencia quedaba en la NPU. En el papel: ¡paralelismo! En las diapositivas: ¡sinergia!
En realidad, crearon un impuesto por movimiento de datos. Los fotogramas iban CPU → GPU para preprocesado, luego GPU → memoria CPU,
luego CPU → NPU. Cada salto implicaba sincronización, copias y conversiones ocasionales de formato. El throughput medio parecía aceptable,
pero la latencia p95 se degradó y el consumo de energía aumentó. El sistema se calentó más y se throttlingeó antes, convirtiendo una mejora en un problema de fiabilidad.
Lo peor: depurar se volvió más difícil. La canalización tenía tres planificadores (CPU, driver GPU, runtime NPU),
y el tiempo dependía de versiones exactas de drivers. Perseguían picos “aleatorios” que en realidad eran contención de colas
y puntos de sincronización entre dispositivos.
Revirtieron la canalización dividida y realizaron un cambio aburrido: mantener el preprocesado en la CPU con kernels vectorizados,
pero agruparlo de forma que alimente eficientemente a la NPU. Menos saltos, menos puntos de sincronización, menor potencia, mejor latencia pico.
El FPS pico bajó ligeramente, pero el sistema dejó de comportarse como poseído.
Segunda broma, y hemos terminado: Añadir un acelerador para arreglar la latencia es como añadir un carril para arreglar el tráfico—a veces solo hiciste el atasco más ancho.
Mini-historia 3: La práctica aburrida pero correcta que salvó el día
Una gran empresa desplegó portátiles con NPUs y una función de supresión de ruido impulsada por IA para llamadas.
El piloto fue bien. El despliegue más amplio no. Usuarios en una región informaron que la función funcionaba a ratos,
luego dejaba de funcionar en silencio y volvía tras reinicios. Comportamiento “intermitente” clásico—el tipo que te come semanas.
El equipo tenía una ventaja: insistieron en una práctica antigua y aburrida desde el principio—inventario de hardware y drivers a nivel de flota,
con líneas base versionadas y detección de deriva. Cada endpoint reportaba IDs de chipset, versiones de driver y si el runtime NPU pasó una autoprueba simple.
Los datos mostraron un patrón rápidamente: las máquinas afectadas compartían un build de driver particular, desplegado vía un anillo regional.
El driver de la NPU se cargaba, pero la inicialización del firmware a veces fallaba tras sleep/resume. El runtime entonces caía a CPU,
y la política de potencia throttlingeaba la CPU bajo llamadas sostenidas, haciendo que la función pareciera “inestable”.
Porque tenían una línea base, pudieron revertir ese anillo y fijar un driver conocido bueno mientras el proveedor arreglaba el problema.
Lo “aburrido”—inventario, despliegues en anillos y una autoprueba—convirtió un desastre intermitente en una regresión controlada.
La lección: las NPUs son hardware. El hardware necesita gestión del ciclo de vida. Trátalo como un clúster, no como un coprocesador mágico.
Errores comunes: síntoma → causa raíz → solución
Estos son los modos de fallo que sigo viendo cuando los equipos “añaden soporte NPU” y luego se preguntan por qué nada mejoró.
1) Síntoma: utilización de NPU casi cero; CPU alta
Causa raíz: El runtime usa ejecución en CPU por proveedor ausente, operadores no soportados o inicialización de dispositivo fallida.
Solución: Verifica la inicialización del dispositivo en dmesg, confirma que el proveedor del runtime esté habilitado e inspecciona qué ops están cayendo a fallback. Convierte el modelo a un set de operadores soportado.
2) Síntoma: la latencia media mejora, pero p95/p99 empeora
Causa raíz: Sincronización entre dispositivos, contención de colas o pre/postprocesado en CPU que se convierte en la causa de cola.
Solución: Minimiza los saltos entre dispositivos, fusiona ops cuando sea posible y perfila toda la canalización. Si hace falta, aísla hilos de inferencia o mueve pre/post al mismo dispositivo.
3) Síntoma: rendimiento genial con AC, terrible con batería
Causa raíz: Cambios de gobernador de potencia, límites PL1/PL2 o el sistema prioriza eficiencia y reduce frecuencia de CPU/GPU mientras la NPU queda infrautilizada.
Solución: Usa APIs OS de QoS de energía, asegúrate de que la inferencia esté realmente en la NPU y prueba en modos de potencia realistas. Ajusta ciclo de trabajo y tamaño de modelo.
4) Síntoma: “NPU es rápida” en demo del proveedor, lenta en tu app
Causa raíz: La demo usa un modelo moldeado para la NPU (ops soportadas, layouts ideales, cuantizado), mientras tu modelo provoca rutas de fallback.
Solución: Re-exporta el modelo con ops compatibles; adopta entrenamiento consciente de cuantización o cuantización post-entrenamiento validada con tus datos; usa herramientas del proveedor para chequear cobertura de operadores.
5) Síntoma: uso de CPU cae, pero la batería sigue sufriendo
Causa raíz: Moviste cómputo fuera de la CPU pero aumentaste tráfico de memoria, wakeups de dispositivo o ejecución constante en segundo plano.
Solución: Añade un presupuesto de actividad. Ejecuta el modelo solo cuando sea necesario, agrupa trabajo y evita mantener el acelerador en un estado de alto consumo contínuo.
6) Síntoma: la inferencia a veces cuelga o expira tras sleep/resume
Causa raíz: Bugs en el ciclo de vida de driver/firmware o runtime que no maneja reinicios del dispositivo con gracia.
Solución: Detecta la salud del dispositivo, reinicia el proveedor del runtime al fallar y mantiene drivers fijados a versiones conocidas buenas con despliegues en anillo.
7) Síntoma: “Más hilos” hace que la inferencia en CPU sea más lenta
Causa raíz: Thrash de caché, saturación de ancho de banda de memoria u oversubscription con otras cargas.
Solución: Ajusta el conteo de hilos al subsistema de memoria; usa pinning NUMA en servidores; mide. Deja de asumir escalado lineal.
8) Síntoma: ruta NPU rápida, pero la calidad de salida empeoró
Causa raíz: Cuantización agresiva o kernels/precisiones diferentes que afectan la numérica.
Solución: Valida la calidad con datos representativos; prefiere entrenamiento consciente de cuantización si es posible; usa cuantización por canal y calibra con entradas reales.
Listas de verificación / plan paso a paso
Paso a paso: decidir si usar CPU, GPU o NPU
- Clasifica la carga: interactiva (latencia estricta), en segundo plano (sensible a potencia), por lotes (throughput) o mixta.
- Mide el ciclo de trabajo: ¿con qué frecuencia se ejecuta la inferencia y por cuánto tiempo? “Ocasional” se vuelve “continuo” con un cambio de producto.
- Perfila la rotura de la canalización: preprocesado, inferencia, postprocesado, E/S y copias entre dispositivos.
- Comprueba cobertura de hardware: ¿qué fracción de la flota tiene una NPU capaz de tu modelo? No optimices para 5% salvo que ese 5% sea tu CEO.
- Comprueba cobertura de operadores: ¿puede la NPU objetivo ejecutar tu grafo sin grandes fallbacks?
- Elige precisión y valida calidad: INT8 puede ser necesario para el rendimiento NPU; demuestra que no rompe casos límite.
- Establece presupuestos: %CPU, estado de potencia, techo térmico y SLOs de latencia.
- Planifica comportamiento de fallback: si la NPU falla, ¿caes a CPU, deshabilitas la función o degradás calidad?
- Implementa observabilidad: registra qué dispositivo ejecutó la inferencia, versión de modelo, precisión y tasas de fallback.
- Despliega en anillos: especialmente drivers/firmware. Trata la pila NPU como tratarías actualizaciones del kernel.
Lista operativa: antes de habilitar una función de IA en toda la flota
- Define objetivos de latencia p50 y p95 para rutas interactivas; define presupuesto medio de potencia para rutas en segundo plano.
- Prueba en modos de ahorro de batería / baja potencia y bajo cargas “peores normales” (videollamada + navegador + EDR).
- Verifica comportamiento tras sleep/resume y manejo de reinicios del dispositivo.
- Confirma tiempo de carga del modelo y huella de memoria; evita swap a toda costa.
- Asegura que tu runtime registre “device selected” y “fallback ops” al menos en nivel debug.
- Fija versiones de driver/runtime por anillo; ten un plan de rollback rápido.
Preguntas frecuentes
1) ¿Las NPUs son solo para portátiles y teléfonos?
No. La etiqueta “NPU” aparece más en dispositivos cliente porque la eficiencia energética importa allí.
En servidores, el mismo concepto existe como aceleradores de inferencia, pero suelen etiquetarse más como GPUs, TPUs o tarjetas.
2) Si tengo una NPU, ¿debería usarla siempre para inferencia?
Solo si tu modelo y runtime realmente encajan bien en ella. Si la cobertura de operadores es pobre, volverás a CPU y perderás rendimiento.
Además, algunas tareas (tokenización, parsing, lógica de negocio) siguen perteneciendo a la CPU.
3) ¿Qué me dice realmente “TOPS”?
Rendimiento teórico pico en condiciones ideales. Es un techo, no un pronóstico.
El verdadero limitador suele ser el ancho de banda de memoria, la cobertura de operadores y cuánto del grafo está realmente acelerado.
4) ¿Por qué a las NPUs les importa tanto la cuantización?
Porque la baja precisión multiplica el rendimiento por vatio y reduce la demanda de ancho de banda de memoria.
Pero la cuantización puede cambiar el comportamiento del modelo; hay que validar calidad, no solo velocidad.
5) ¿Una NPU puede ayudar con LLMs específicamente?
A veces, para modelos más pequeños o cuantizados y para operadores específicos. Pero muchas NPUs cliente están optimizadas para grafos de visión/audio.
La inferencia de LLMs suele estar limitada por memoria y puede no mapear bien sin soporte cuidadoso de kernels y runtime.
6) ¿Cuál es la mayor razón por la que “el soporte NPU” no mejora el rendimiento?
El fallback. Una operación no soportada puede forzar saltos entre dispositivos o ejecución en CPU para grandes partes del grafo.
Mide siempre qué ops se ejecutaron dónde.
7) ¿Las NPUs son más fiables que las GPUs?
Diferentes modos de fallo. Las NPUs están integradas y a menudo son más simples de gestionar en potencia, pero la madurez del driver/runtime varía.
Las GPUs tienen pilas maduras en muchos entornos, pero añaden complejidad y consumo de potencia. La fiabilidad depende sobre todo de la gestión del ciclo de vida y la observabilidad.
8) ¿Qué debería registrar en producción para evitar conjeturas?
Registra el dispositivo de ejecución (CPU/GPU/NPU), versión del modelo y precisión, conteo de ops en fallback, latencia de inferencia (p50/p95)
y cualquier error de reset/inicialización del dispositivo. Sin eso, estarás depurando sensaciones.
9) ¿Cómo decido si mover el preprocesado también a la NPU?
Prefiere mantener los datos en un solo dispositivo cuando sea posible, pero no lo fuerces. Si el preprocesado es pequeño y con muchas ramas, la CPU está bien.
Muévelo solo cuando las copias dominen o el acelerador tenga soporte dedicado para esas ops.
10) ¿Cuál es la “victoria” más sencilla para inferencia en CPU si no puedo usar una NPU?
Cuantiza, ajusta el conteo de hilos, evita swap y corrige la colocación NUMA en servidores. Luego perfila la canalización.
La mayoría de los informes “la CPU va lenta” en realidad son informes de “la memoria va lenta”.
Siguientes pasos prácticos
Si eres responsable de desplegar una función de IA en máquinas reales, haz lo siguiente:
- Mide dónde se ejecuta el trabajo (CPU vs NPU vs GPU) y con qué frecuencia cae a fallback.
- Perfila la latencia de extremo a extremo, no solo el runtime del modelo.
- Establece presupuestos: utilización de CPU, margen térmico y impacto en batería son requisitos, no añadidos.
- Elige una estrategia de modelo: cuantiza con validación de calidad, o acepta menor rendimiento. No finjas que obtienes ambos gratis.
- Operacionaliza el hardware: líneas base de drivers, despliegues en anillos y planes de rollback. Trata la habilitación NPU como un cambio de kernel.
Las NPUs no existen porque las CPU sean “malas”. Existen porque la física es ruda, las baterías son pequeñas y los usuarios se quejan de inmediato.
Pon el trabajo correcto en el silicio correcto y mantén tus sistemas aburridos. Lo aburrido escala.