¿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.
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 totales | Hilos activos | % CPU aproximado |
---|---|---|
8 | 1 | ≈ 12% |
16 | 1 | ≈ 6% |
16 | 2 | ≈ 12% |
16 | 3 | ≈ 19% |
24 | 3 | ≈ 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
- Genera todos los aleatorios de una sola vez con
RANDARRAY
. - Evalúa cada fila con
BYROW
+LAMBDA
y, si hace falta,SCAN
/MAP
. - 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 deIF/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 conIF
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
- 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
). - 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))
- Regla de victoria (ejemplo: aparece un 12):
=suma = 12
- Primer lanzamiento que cumple por fila:
=BYROW(suma=12, LAMBDA(fila, XMATCH(TRUE, fila, 0)))
- Éxito y agregados:
=LET(pos, <paso anterior>, exito, ISNUMBER(pos), HSTACK( "P(éxito)", AVERAGE(--exito), "Prom. tiradas", AVERAGE(FILTER(pos, exito)) ))
- 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:
- 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.
- Rellena hacia abajo hasta 100 000 filas.
- 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:
- Abrir nueva instancia: mantén Alt y haz clic en el icono de Excel; confirma.
- Divide los 100 000 casos en, por ejemplo, 10 libros con 10 000 cada uno.
- 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
Estrategia | Ganancia esperada | Complejidad | Cuándo usar |
---|---|---|---|
Tabla de datos (base) | — | Baja | Prototipo, tamaños pequeños (< 5 000) |
RandArray + ByRow | Alta (×3–×20) | Media | 365 disponible y lógica por filas |
Modelo tabular clásico | Media–Alta | Media | Sin funciones 365; filas independientes |
Varias instancias de Excel | Alta (escala por núcleos) | Media–Alta | Necesario mantener Tabla de datos |
Python/R/C# fuera de Excel | Muy alta (milisegundos) | Media–Alta | Agregados, 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
; usaXMATCH
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, ...)