← volver a la demostración

Demostración de TAKT: predicción de series temporales en Rust (DLinear y PatchTST sobre ETT)

Dos modelos estándar de predicción a largo plazo, DLinear (LTSF-Linear) y PatchTST, entrenados con los scripts oficiales sobre los conjuntos de datos ETT, traducidos de PyTorch a Rust puro (sin BLAS ni runtime de ML) y compilados dos veces: la compilación original de ese código Rust y la compilación de TAKT del mismo código. Las predicciones de ambas compilaciones son idénticas bit a bit. Aquí encontrará programas listos para ambas compilaciones, el código fuente de la versión original, un script que recrea las ventanas de entrada a partir de los datos oficiales, un script de benchmark y nuestras mediciones.

Qué calculan los programas

Todas las ventanas de la partición de prueba de un conjunto ETT (límites oficiales, features M, StandardScaler ajustado sobre la partición de entrenamiento): de entrada, 336 pasos anteriores x 7 canales; de salida, los 96 pasos siguientes x 7 canales; float32. ETTh1/ETTh2: 2.785 ventanas; ETTm1/ETTm2: 11.425 ventanas. Los pesos del checkpoint del conjunto seleccionado están compilados dentro del programa (--data).

Modelo Conjunto MSE / MAE de prueba (todas las ventanas, tools/score.py) Ejecución oficial de entrenamiento, prueba
DLinear ETTh1 0,384144 / 0,404713 0,384144 / 0,404713
DLinear ETTh2 0,290098 / 0,353328 0,290098 / 0,353328
DLinear ETTm1 0,301222 / 0,344619 0,301222 / 0,344619
DLinear ETTm2 0,171852 / 0,267122 0,171852 / 0,267122
PatchTST ETTh1 0,385126 / 0,405953 (primeras 2.688: 0,381618 / 0,405088) 0,381618 / 0,405088
PatchTST ETTh2 0,274616 / 0,337234 (primeras 2.688: 0,274118 / 0,336000) 0,274117 / 0,336000

El bucle de prueba oficial de PatchTST descarta el último lote incompleto de 128 ventanas; de ahí la columna «primeras 2.688». La traducción a Rust no es idéntica bit a bit a PyTorch (otro orden de suma; la mayor diferencia absoluta respecto a PyTorch eager es de 2e-6 a 2e-5); la compilación de TAKT es idéntica bit a bit al original en Rust.

Medición (banco de TAKT)

Medido el 3 de octubre de 2026. AMD Threadripper PRO 5975WX (Zen 3), Linux. Un CCX de 8 núcleos reservado, con sus hilos SMT gemelos inactivos; las ejecuciones de un hilo se fijan a un núcleo, y las de ocho hilos, a los 8 núcleos del CCX. Para cada conjunto: un par de calentamiento y luego 9 rondas en orden alterno, mediana. Tiempo: el bucle de predicción, cronometrado por el propio programa (se excluyen la lectura de las ventanas y la escritura de las predicciones, que cuestan lo mismo en ambas compilaciones). Ciclos: ciclos en modo usuario del mismo bucle (perf stat, sumados en todos los hilos). Ambas compilaciones comparten el mismo programa de control, que conserva en el proceso la memoria de heap liberada (mallopt de glibc), como haría un servicio de larga duración, para que los búferes temporales de cada ventana no se conviertan en fallos de página. Se midieron exactamente los archivos de bin/, con tools/run_bench.sh.

Modelo Conjunto Ventanas Hilos Original, ms TAKT, ms Aceleración Original, M ciclos TAKT, M ciclos Aceleración en ciclos Rondas idénticas
DLinear ETTh1 2.785 1 788,4 111,0 7,10× 3.518 486 7,23× 9/9
DLinear ETTh2 2.785 1 785,0 108,4 7,24× 3.512 476 7,38× 9/9
DLinear ETTm1 11.425 1 3.223,9 447,8 7,20× 14.421 1.978 7,29× 9/9
DLinear ETTm2 11.425 1 3.228,4 442,6 7,29× 14.405 1.984 7,26× 9/9
DLinear ETTh1 2.785 8 103,3 14,5 7,11× 3.515 486 7,23× 9/9
DLinear ETTh2 2.785 8 103,3 14,2 7,26× 3.514 477 7,37× 9/9
DLinear ETTm1 11.425 8 423,3 58,6 7,22× 14.426 1.988 7,26× 9/9
DLinear ETTm2 11.425 8 422,1 58,9 7,17× 14.407 1.998 7,21× 9/9
PatchTST ETTh1 2.785 1 13.440,8 5.733,4 2,34× 59.973 25.507 2,35× 9/9
PatchTST ETTh2 2.785 1 13.484,3 5.749,2 2,35× 60.068 25.645 2,34× 9/9
PatchTST ETTh1 2.785 8 1.777,5 765,7 2,32× 60.424 25.955 2,33× 9/9
PatchTST ETTh2 2.785 8 1.785,3 769,3 2,32× 60.677 26.070 2,33× 9/9

DLinear: 7,1–7,3× en tiempo y 7,2–7,4× en ciclos, con uno y con ocho hilos. PatchTST: 2,3× en tiempo y en ciclos. Con ocho hilos, ambas compilaciones gastan en total aproximadamente los mismos ciclos que con uno. El proceso completo, incluidas la lectura de 26–107 MB de ventanas y la escritura de las predicciones, es 5,7–6,0× más rápido para DLinear con un hilo, 3,0–3,1× con ocho y 2,3× para PatchTST. Los detalles, las muestras sin procesar y los tiempos del proceso completo están en measurements.json.

Ejecución

python3 tools/make_windows.py --out data --targets   # descarga los CSV oficiales de ETT (verificados con sha256),
                                                     # escribe data/windows_*_test.f32 (y los valores objetivo)
mkdir -p out
for d in ETTh1 ETTh2 ETTm1 ETTm2; do
  bin/ltsf-dlinear-takt --data $d --windows data/windows_${d}_test.f32 --threads 1 --out out/dlinear_$d.f32
done
for d in ETTh1 ETTh2; do
  bin/ltsf-patchtst-takt --data $d --windows data/windows_${d}_test.f32 --threads 1 --out out/patchtst_$d.f32
done
sha256sum -c expected.sha256                 # ventanas, valores objetivo y predicciones como en nuestra medición
python3 tools/score.py data/targets_ETTh1_test.f32 out/dlinear_ETTh1.f32

tools/run_bench.sh -m dlinear -n 9 -c 2          # ambas compilaciones, intercaladas, verificación byte a byte, núcleo 2
tools/run_bench.sh -m dlinear -n 9 -t 8 -c 2-9   # ocho hilos en los núcleos 2-9
tools/run_bench.sh -m patchtst -n 9 -c 2

--threads T admite cualquier T >= 1; las predicciones no dependen de T. Los archivos de entrada y salida son float32 little-endian sin formato (n x 336 x 7 y n x 96 x 7); tools/make_windows.py solo necesita numpy.

Linux x86-64 (glibc). Los programas están compilados para x86-64-v3 (AVX2, FMA, BMI2: Intel Haswell y posteriores, AMD Zen y posteriores); no se usan instrucciones FMA. PatchTST llama a erff de la biblioteca C del sistema: con una glibc cuya erff difiera de la de glibc 2.39 (Ubuntu 24.04), sus predicciones pueden diferir de expected.sha256, mientras que el original y la compilación de TAKT siguen coincidiendo byte a byte.

Equivalencia

Recompilar el original

cd source
RUSTFLAGS="-C target-cpu=x86-64-v3 --remap-path-prefix=$HOME/.rustup=. \
  --remap-path-prefix=$HOME/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f=." \
  cargo +1.96.0 build --release --locked
strip --strip-all -o ltsf-dlinear-original target/release/ltsf-dlinear

Con Rust 1.96.0 de rustup (con el componente rust-src), esto reproduce bit a bit bin/ltsf-dlinear-original y bin/ltsf-patchtst-original en nuestra máquina; con otra configuración cambian las rutas incrustadas, pero no las predicciones.

Comparación anterior con PyTorch (no reproducible con este paquete)

El 2 de octubre de 2026 medimos los mismos modelos en la misma máquina en otras condiciones: sin reserva del banco (39 CPU lógicas compartidas con otras tareas); ambas versiones en Rust compiladas como bibliotecas compartidas para la CPU nativa y llamadas dentro del proceso; PyTorch 2.14 en la CPU, eager y torch.compile (Inductor), lotes de 64 o 512. Para cada implementación, el número de hilos (1, 8 o 32) y el tamaño de lote se eligieron por la menor latencia en la partición de validación, y después se cronometró la partición de prueba (mediana de 5).

Modelo Conjunto Rust original Compilación de TAKT PyTorch más rápido (Inductor) PyTorch / TAKT
DLinear ETTh1 28,7 ms (32 hilos) 5,1 ms (32) 18,5 ms (32, lote 512) 3,63×
DLinear ETTh2 30,1 ms (32) 5,3 ms (32) 12,5 ms (32, lote 512) 2,34×
DLinear ETTm1 115,4 ms (32) 19,7 ms (32) 65,1 ms (8, lote 512) 3,31×
DLinear ETTm2 114,9 ms (32) 20,4 ms (32) 49,5 ms (32, lote 512) 2,43×
PatchTST ETTh1 593 ms (32) 236 ms (32) 634 ms (32, lote 64) 2,69×
PatchTST ETTh2 519 ms (32) 234 ms (32) 551 ms (32, lote 64) 2,35×

Con un hilo, el orden fue distinto: PyTorch con Inductor y lotes fue más rápido que la compilación de TAKT (DLinear ETTh1: 37,9 ms frente a 111,4 ms; PatchTST ETTh1: 2,03 s frente a 5,78 s). En esa ejecución, la compilación de TAKT fue 5,6–5,9× (DLinear) y 2,2–2,5× (PatchTST) más rápida que el Rust original con los 32 hilos seleccionados, y 7,2–7,3× y 2,3× más rápida con un hilo. Todas las cifras de esa ejecución están en measurements.json (earlier_measurement_2026_10_02).

Contenido

Los datos ETT no se incluyen (CC BY-ND 4.0; los descarga tools/make_windows.py). El código fuente de la compilación de TAKT no se publica: entregamos compilaciones.

Texto original: README.es.md

Telegram