Excel solo usa ~15% de CPU con 100 000 simulaciones: causas y cómo acelerarlo

¿Tu simulación de dados en Excel tarda minutos y el Administrador de tareas muestra apenas ~15% de CPU? No es que tu PC “se quede corta”, sino que la arquitectura de cálculo de Excel limita cómo se reparte el trabajo. Aquí tienes la explicación y varias rutas para acelerarlo sin sacrificar resultados.

Índice

Resumen de la pregunta

Un modelo en Excel ejecuta un juego de dados. Una Tabla de datos (What‑If) fuerza el recálculo 100 000 veces de una misma cadena de fórmulas que puede generar hasta 75 números aleatorios por “partida”. El cálculo completo tarda ~10 min y el uso de CPU se queda en ~15% pese a un equipo moderno. ¿Por qué ocurre y cómo mejorarlo?

Por qué Excel muestra ~15% de CPU aunque el equipo sea potente

Las Tablas de datos son monohilo y secuenciales

Aunque Excel soporta cálculo multihilo, esa optimización no aplica a las Tablas de datos. Su motor ejecuta la cadena del “modelo base” una vez por fila (o columna) y en un único hilo. Si pides 100 000 iteraciones, Excel recorre 100 000 veces la misma ruta, una detrás de otra.

Volatilidad y dependencia completa

Funciones como RAND() y RANDBETWEEN() son volátiles: al cambiar cualquier cosa, siempre se recalculan. En una Tabla de datos, todo depende de una única fila “modelo”, así que la cadena se vuelve a ejecutar completa en cada iteración. Si cada partida genera hasta 75 aleatorios, multiplicas el trabajo por 100 000.

Coste de I/O a la cuadrícula y orquestación

Una fracción importante del tiempo se va en leer/escribir celdas y coordinar dependencias (gráfica de cálculo). No es un problema de RAM, sino de cómo Excel conversa con la hoja de cálculo a nivel de celdas.

Interpretación del “15%” en el Administrador de tareas

Si tu CPU tiene, por ejemplo, 8 núcleos/16 hilos lógicos, 1 hilo ocupado equivale a ~6% de CPU; 2–3 hilos rondan 12–19%. Ver ~15% encaja con “uno o pocos hilos saturados”, no con falta de trabajo. Es una limitación por diseño, no un cuello de botella de hardware.

Hilos lógicos totalesHilos activos% CPU aproximado
81≈ 12%
161≈ 6%
162≈ 12%
163≈ 19%
243≈ 12%

Cómo acelerarlo de verdad

Evitar la Tabla de datos y paralelizar por filas

Impacto alto. Reestructura el modelo para que cada partida viva en su propia fila y todas las filas sean independientes. Así Excel puede repartir el cálculo en varios hilos.

Opción dinámica con Excel 365

  1. Genera todos los aleatorios de una sola vez con RANDARRAY.
  2. Evalúa cada fila con BYROW + LAMBDA y, si hace falta, SCAN/MAP.
  3. Devuelve solo los agregados (reduces I/O a la cuadrícula).

Plantilla de fórmula 365 (dos dados, 100 000 partidas, 75 lanzamientos)

=LET(
  n, 100000,              / partidas /
  t, 75,                  / lanzamientos por partida /
  d1, RANDARRAY(n, t, 1, 6, TRUE),
  d2, RANDARRAY(n, t, 1, 6, TRUE),
  suma, d1 + d2,          / 2..12 /
  objetivo, 12,           / regla ejemplo: aparece un 12 /
  cond, suma = objetivo,
  pos, BYROW(cond, LAMBDA(fila, XMATCH(TRUE, fila, 0))),     / 1..t o #N/A /
  exito, ISNUMBER(pos),
  ganadas, FILTER(pos, exito),
  VSTACK(
    HSTACK("Corridas", n),
    HSTACK("P(éxito)", AVERAGE(--exito)),
    HSTACK("Prom. tiradas (si hay 12)", AVERAGE(ganadas))
  )
)

Notas: XMATCH(TRUE, ...) localiza el primer lanzamiento que cumple la condición sin “bucles ocultos”. Usar FILTER evita que #N/A contamine agregados. Este enfoque permite a Excel paralelizar filas.

Opción tabular clásica

Clona el “modelo por partida” a 100 000 filas (una partida por fila, sin Tabla de datos) y agrega con fórmulas aparte. Excel suele multihilar regiones independientes más eficazmente que una Tabla de datos.

Reducir volatilidad y llamadas aleatorias

  • Genera los aleatorios en bloque (una vez) y reutilízalos en la lógica. Si deseas fijarlos, Pegar valores.
  • Evita anidar muchos RANDBETWEEN dentro de IF/IFS. Calcula antes los aleatorios y luego decide sobre ellos.
  • Para “primer lanzamiento que cumple X”, usa XMATCH(TRUE, condición, 0) en vez de patrones con IF concatenados.

Controlar el recálculo

  • Usa Automático excepto Tablas de datos o Manual para evitar recálculos involuntarios durante la edición.
  • Si usas VBA u Office Scripts, agrupa operaciones: escribe rangos grandes de una sola vez y minimiza lecturas/escrituras por celda.

Dividir y conquistar si debes seguir con Tabla de datos

  • Parte los 100 000 casos en bloques (p. ej., 10 hojas de 10 000).
  • Avanzado: abre instancias separadas de Excel (Alt+clic en el icono, confirma). Cada proceso puede usar su propio núcleo. Asigna un bloque por proceso y combina los resultados al final.

Mover la simulación fuera de la hoja

Si tu objetivo son estadísticas agregadas (probabilidades, medias, percentiles), Python (NumPy), R o C# ejecutan millones de sorteos en milisegundos y devuelven a Excel solo el resultado.Ejemplo NumPy (esqueleto)

import numpy as np
n, t = 100_000, 75
d = np.random.randint(1, 7, (n, t)) + np.random.randint(1, 7, (n, t))
cond = (d == 12)
wins = cond.any(axis=1)
first = np.where(wins, cond.argmax(axis=1) + 1, np.nan)
p_win = wins.mean()
avg_rolls = np.nanmean(first)

Higiene del modelo

  • Verifica en Archivo ▸ Opciones ▸ Fórmulas: Habilitar cálculo de varios subprocesos y Usar todos los procesadores de este equipo.
  • Simplifica con LET/LAMBDA para no repetir cálculos.
  • Cuestiona el tamaño de muestra: en proporciones, el error estándar cae como √(p(1−p)/n); a menudo 10–50 k corridas bastan.

Implementación paso a paso en Excel 365 sin Tabla de datos

  1. Define parámetros cerca del área de trabajo (por ejemplo, en celdas dedicadas o dentro de LET): número de partidas (n) y lanzamientos por partida (t).
  2. Genera tiradas de dos dados en una matriz n×t: =LET(n,100000, t,75, RANDARRAY(n,t,1,6,TRUE) + RANDARRAY(n,t,1,6,TRUE))
  3. Regla de victoria (ejemplo: aparece un 12): =suma = 12
  4. Primer lanzamiento que cumple por fila: =BYROW(suma=12, LAMBDA(fila, XMATCH(TRUE, fila, 0)))
  5. Éxito y agregados: =LET(pos, <paso anterior>, exito, ISNUMBER(pos), HSTACK( "P(éxito)", AVERAGE(--exito), "Prom. tiradas", AVERAGE(FILTER(pos, exito)) ))
  6. Congela aleatorios si vas a iterar diseño: selecciona el rango, Copiar ▸ Pegar valores.

Con este patrón, Excel puede dividir por hilos (cada fila es independiente) y reduce el tiempo drásticamente frente a la Tabla de datos.

Implementación tabular clásica con multihilo

Si no tienes funciones dinámicas o prefieres fórmulas tradicionales:

  1. Diseña el modelo de una partida por fila (ej.: columnas A:BW para 75 lanzamientos, BX resultado, BY índice). Asegúrate de que las fórmulas solo referencian la misma fila.
  2. Rellena hacia abajo hasta 100 000 filas.
  3. Coloca agregados en otra área (p. ej., SUMPRODUCT, AVERAGEIF sobre el rango de 100 000 filas).

Excel paraleliza hojas con ramos independientes mucho mejor que las Tablas de datos; en equipos con muchos hilos sueles ver mejoras claras.

VBA/Office Scripts para recálculo controlado

Cuando necesites poblar grandes bloques de resultados o ejecutar lotes sin “parpadeos” en la interfaz, usa un patrón que desactive/active cálculo y pantalla una sola vez:VBA minimalista para rellenar n×t tiradas (dos dados)

Sub SimularDados()
    Dim n As Long: n = 100000
    Dim t As Long: t = 75
    Dim arr() As Integer
    ReDim arr(1 To n, 1 To t)
    Dim i As Long, j As Long
    Randomize
    For i = 1 To n
        For j = 1 To t
            arr(i, j) = Int(6  Rnd) + 1 + Int(6  Rnd) + 1
        Next j
    Next i
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    With Sheets("Sim")
        .Range("A2").Resize(n, t).Value2 = arr
    End With
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
End Sub

El punto clave es escribir el arreglo completo a la hoja de una vez (batch write), en lugar de tocar celdas una a una.

Paralelizar por procesos con varias instancias de Excel

Una sola instancia de Excel no aprovechará todos los núcleos si el cálculo está anclado a un hilo (como en Tablas de datos). Abre varias instancias independientes y reparte el trabajo:

  1. Abrir nueva instancia: mantén Alt y haz clic en el icono de Excel; confirma.
  2. Divide los 100 000 casos en, por ejemplo, 10 libros con 10 000 cada uno.
  3. Ejecuta cada libro en una instancia distinta. Combina al final (copiar valores o Power Query).

Cada proceso tendrá su propio hilo principal; así puedes subir del ~15% a porcentajes cercanos a la ocupación total del procesador.

Comparativa rápida de estrategias

EstrategiaGanancia esperadaComplejidadCuándo usar
Tabla de datos (base)BajaPrototipo, tamaños pequeños (< 5 000)
RandArray + ByRowAlta (×3–×20)Media365 disponible y lógica por filas
Modelo tabular clásicoMedia–AltaMediaSin funciones 365; filas independientes
Varias instancias de ExcelAlta (escala por núcleos)Media–AltaNecesario mantener Tabla de datos
Python/R/C# fuera de ExcelMuy alta (milisegundos)Media–AltaAgregados, cargas masivas

Diagnóstico y medición

  • Tiempo de recálculo: en Manual, inserta =NOW() en una celda auxiliar; pulsa F9 y cronometra.
  • Recalcular todo: usa Ctrl+Alt+F9 para una reconstrucción completa y medir “lo peor”.
  • Prueba A/B: corre 10 000 vs. 100 000 y compara tiempos; el crecimiento casi lineal delata cálculo secuencial.
  • Observa CPU: si una alternativa sube de 15% a 80–100% durante cálculo, lograste paralelizar o abrir procesos en paralelo.

Preguntas frecuentes

¿Por qué Excel tiene multihilo si aquí no se usa?

Excel paraleliza bien cuando existen ramos independientes en la gráfica de cálculo (miles de celdas sin dependencia cruzada). Pero características históricas como Tablas de datos, algunas UDFs complejas, iteración por circularidad, etc., siguen siendo monohilo por motivos de determinismo y arquitectura.

¿Cambiar de “Automático” a “Manual” acelera?

No acelera el cálculo en sí; solo evita recálculos repetidos mientras editas. Úsalo para controlar cuándo recalcula.

¿Los 100 000 casos son imprescindibles?

Para estimar probabilidades, el error estándar de una proporción es √(p(1−p)/n). Duplicar n reduce el error solo √2 veces. Valora si 10–50 k cubren tu necesidad con margen.

¿Volatilidad solo afecta a RAND/RANDBETWEEN?

No. También son volátiles NOW(), TODAY(), OFFSET(), INDIRECT(), etc. Úsalas con cuidado en modelos grandes.

Checklist accionable

  • Deshaz la Tabla de datos; reestructura “por filas”.
  • Genera aleatorios con RANDARRAY en bloque y reutiliza.
  • Evalúa cada fila con BYROW + LAMBDA; usa XMATCH para “primera coincidencia”.
  • Agrega resultados y devuelve solo métricas clave para reducir I/O.
  • Activa “usar todos los procesadores” y calcula en Manual durante la edición.
  • Escala con varias instancias o mueve a Python si necesitas millones de corridas.

Conclusión

El ~15% de CPU durante tu simulación es un síntoma de monohilo, no de falta de potencia. Las Tablas de datos fuerzan un patrón secuencial que atasca el rendimiento. Cuando desacoplas por filas, reduces volatilidad y controlas el recálculo, Excel libera sus hilos y los tiempos caen de minutos a segundos. Y si necesitas aún más, paraleliza por procesos o externaliza a un motor numérico. El resultado: mismas respuestas en menos tiempo, y una hoja que escala con tu hardware.

Apéndice de fórmulas útiles

  • Primer índice que cumple: XMATCH(TRUE, condicion_array, 0)
  • Proporción de éxitos: AVERAGE(--boolean_array)
  • Media condicionada: AVERAGE(FILTER(valores, mascara))
  • Acumular por fila: BYROW(matriz, LAMBDA(f, ...))
  • Nombres intermedios (evitar repetir): LET(nombre, valor, ...)
Índice