← volver a la demostración

Demostración de TAKT: descompresión bzip2 (corpus Silesia)

Un programa en dos compilaciones: bz2dec descomprime archivos .bz2 a la salida estándar, como bzip2 -dc. bz2dec-original usa el crate bzip2-rs 0.1.2 (un decodificador bzip2 escrito íntegramente en Rust) tal como está publicado en crates.io; bz2dec-takt usa el mismo crate tras la optimización de TAKT. El programa de control es el mismo archivo fuente, la receta de compilación es la misma y la salida de ambos programas es idéntica byte a byte. Aquí encontrará los dos programas listos, el código fuente de la compilación original, un script que descarga el corpus y los scripts que repiten la medición y las verificaciones.

Qué hace el benchmark

Los doce archivos del corpus Silesia (texto, ejecutables, bases de datos, imágenes, XML; 211.938.580 bytes), cada uno comprimido con bz2.compress(data, 9) de Python (libbz2 1.0.8, un flujo por archivo, 54.506.769 bytes en total), se descomprimen en un solo proceso:

bz2dec -c dickens.bz2 mozilla.bz2 mr.bz2 nci.bz2 ooffice.bz2 osdb.bz2 reymont.bz2 \
          samba.bz2 sao.bz2 webster.bz2 xml.bz2 x-ray.bz2 > /dev/null

Como comparación, el bzip2 -dc del sistema (la implementación de referencia en C) ejecuta la misma tarea.

Medición (banco de TAKT)

AMD Threadripper PRO 5975WX (Zen 3), Linux, un núcleo dedicado (su hilo SMT gemelo inactivo y su CCX reservado para la medición). perf stat cuenta los ciclos y las instrucciones en modo usuario del proceso de decodificación, así como su tiempo de reloj; 9 rondas intercaladas (el orden de los programas rota de una ronda a otra), mediana. Se midieron exactamente estos archivos. Los tres programas son ejecutables glibc con enlace dinámico; las dos compilaciones de bz2dec usan la misma receta: Rust 1.96.0, LTO, codegen-units 1, target-cpu=x86-64-v3, panic abort, sin símbolos.

El conjunto completo, un proceso por programa:

Programa Decodificador Ciclos, M Instrucciones, M Tiempo, ms MB/s Aceleración
bz2dec-original bzip2-rs 0.1.2 de crates.io 17.867,0 22.191,1 4.129 51,3 1,00×
bzip2 -dc bzip2 en C / libbz2 1.0.8 (paquete de Ubuntu 24.04) 21.148,9 25.378,5 4.884 43,4 0,84×
bz2dec-takt el mismo crate tras la optimización de TAKT 5.104,7 10.028,5 1.204 176,0 3,50×

bz2dec-takt frente al bzip2 -dc en C: 4,14× en ciclos, 4,06× en tiempo. Frente a bz2dec-original en tiempo: 3,43×. La aceleración es el cociente de las medianas de ciclos; MB/s son megabytes descomprimidos (10⁶ bytes) por segundo de tiempo de reloj.

Cada archivo en su propio proceso (las mismas rondas; tiempo en ms, aceleración en ciclos):

Archivo Sin comprimir, MB Original, ms TAKT, ms bzip2 -dc, ms frente al original frente a bzip2 -dc
dickens 10,2 247,3 65,8 286,7 4,16× 4,82×
mozilla 51,2 1.048,6 370,9 1.272,9 2,96× 3,64×
mr 10,0 177,2 48,4 206,1 4,04× 4,64×
nci 33,6 461,7 111,0 516,6 4,32× 4,81×
ooffice 6,2 169,4 59,0 205,5 3,20× 3,95×
osdb 10,1 229,3 63,0 265,5 3,92× 4,68×
reymont 6,6 136,0 35,8 152,9 4,25× 4,87×
samba 21,6 333,1 115,0 404,9 3,08× 3,75×
sao 7,3 241,3 85,7 270,0 3,05× 3,43×
webster 41,5 843,6 216,1 972,2 4,10× 4,79×
xml 5,3 72,3 20,9 82,6 4,04× 4,64×
x-ray 8,5 236,4 80,1 255,6 3,22× 3,50×

La aceleración depende de los datos: de 2,96× a 4,32× frente al original y de 3,43× a 4,87× frente a bzip2 -dc en estos archivos. El tiempo de reloj incluye también el arranque del proceso, la lectura de la entrada y el trabajo del kernel, que son iguales para todos los programas; por eso los cocientes en tiempo son algo menores que los cocientes en ciclos. Otros datos y otras CPU darán otras cifras. Los detalles y todas las muestras están en measurements.json.

Ejecución

python3 tools/fetch_silesia.py      # descarga silesia.zip (68 MB), lo verifica y escribe data/raw y data/bz2
tools/run_bench.sh 7 2              # verifica cada byte de salida y luego hace 7 rondas intercaladas en el núcleo 2
bin/bz2dec-takt -c data/bz2/dickens.bz2 | cmp - data/raw/dickens      # idénticos byte a byte
sha256sum -c SHA256SUMS

tools/fetch_silesia.py solo necesita Python 3 y verifica el archivo comprimido (sha256) y cada archivo del corpus (tamaño, el MD5 publicado en la página del corpus, sha256); también le indica si sus entradas .bz2 son exactamente los bytes que medimos. tools/run_bench.sh también cuenta ciclos cuando perf está disponible.

Uso: bz2dec -c FILE.bz2 [FILE.bz2 ...] > OUT. Códigos de salida: 0, éxito; 1, error de uso, de E/S o de CPU; 2, flujo no válido (el mensaje de error del decodificador se imprime en stderr); 3, error interno del decodificador.

Linux x86-64 (glibc). Ambos programas están compilados para x86-64-v3: AVX2, BMI1, BMI2, FMA (Intel Haswell y posteriores, AMD Zen y posteriores); no funcionan en CPU más antiguas.

Equivalencia

Compilar el original

cd source
RUSTFLAGS="-C target-cpu=x86-64-v3 --remap-path-prefix=$(ls -d ~/.cargo/registry/src/index.crates.io-*)=. \
  --remap-path-prefix=$HOME/.rustup=. --remap-path-prefix=$PWD=." cargo +1.96.0 build --release --locked
strip --strip-all target/release/bz2dec

En nuestra verificación, esto reconstruyó bin/bz2dec-original bit a bit (Rust 1.96.0 de rustup, en otro directorio). bin/bz2dec-takt es el mismo source/src/main.rs enlazado con la compilación de TAKT del crate, que conserva la API pública del crate, su tipo de error y sus mensajes.

Contenido

No se publica el código fuente de la compilación de TAKT de bzip2-rs: entregamos compilaciones.

Texto original: README.es.md

Telegram