Zstd: Mejor relación de compresión si el contexto de compresión se descarta periódicamente

Creado en 8 jul. 2019  ·  3Comentarios  ·  Fuente: facebook/zstd

Constantemente obtengo una relación de compresión ligeramente mejor si el contexto de compresión no se reutiliza.
Estoy creando un contexto de compresión ZSTD, luego en un bucle llamando a ZSTD_compressCCtx, cada vez dando 1 MB de búfer con datos. Al final del proceso, se libera el contexto de compresión.
Si libero el contexto de compresión y creo uno nuevo antes de proceder a comprimir el siguiente búfer de 1 MB, el tamaño del archivo de salida es consistentemente alrededor de un 1% más pequeño.
Otro dato interesante es que la relación de compresión es alrededor de 1 a 1,5% mejor si estoy usando búferes de entrada de 2 MB con datos, en comparación con búferes de entrada de 1 MB.
En mi caso de uso, no estoy limitado por los recursos de memoria.
Preguntas)

  • ¿Es una mejor práctica descartar el contexto de compresión entre la compresión de grandes fragmentos de datos?

    • ¿Cuál es el tamaño de búfer de entrada óptimo recomendado (es decir, la disminución del tamaño del búfer degradará el índice de compresión, mientras que el aumento del tamaño del búfer no mejorará el índice de compresión)?

    • Cualquier forma de decirle a zstd "usa tanta memoria como quieras pero dame una mejor relación de compresión y / o velocidad"

    • ¿Realmente la compresión de transmisión con contexto es buena solo para casos de uso con limitaciones de memoria? Si tengo mucha memoria, ¿estoy mejor comprimiendo de forma independiente búferes grandes (> 1 MB)?

question

Todos 3 comentarios

Hola @scherepanov ,

este resultado es sorprendente.
Usando ZSTD_compressCCtx() , con la misma entrada y el mismo nivel de compresión, no debería importar (desde la perspectiva de la relación de compresión) si el contexto se reutiliza o no. El único impacto de reutilizar el contexto es ahorrar tiempo de asignación e inicialización, eso es todo. Si afecta la relación de compresión, es extraño y probablemente esté mal.

Me gustaría reproducir este escenario si es posible. Qué versión está utilizando ?

¿Es una mejor práctica descartar el contexto de compresión entre la compresión de grandes fragmentos de datos?

Nunca debería necesitar descartar el contexto.
La única "buena" razón para hacerlo es simplificar el código.
Pero desde una perspectiva de desempeño, solo debería ser beneficioso, sin inconvenientes.

¿Cuál es el tamaño de búfer de entrada óptimo recomendado?

Esto es muy situacional. No existe un umbral "universal".
En términos generales, más allá del tamaño de ventana 8x, aumentar el tamaño del fragmento es cada vez menos valioso.
El tamaño de la ventana, sin embargo, es un valor dinámico, dependiendo del nivel de compresión.
Varía de 512 KB (nivel 1) a 8 MB (nivel 19).

Cualquier forma de decirle a zstd "usa tanta memoria como quieras pero dame una mejor relación de compresión"

Se supone que el nivel 19 es de este tipo

y / o velocidad "

El nivel 4 es generalmente de este tipo: se comprime bastante rápido, pero utiliza una gran cantidad de memoria. Eso es lo más cercano que puedo pensar.

¿Realmente la compresión de transmisión con contexto es buena solo para casos de uso con limitaciones de memoria? Si tengo mucha memoria, ¿estoy mejor comprimiendo de forma independiente búferes grandes (> 1 MB)?

Comprimir / descomprimir fragmentos independientes en una sola pasada ( ZSTD_compressCCtx() y ZSTD_decompressDCtx() ) es simplemente más simple y probablemente tan eficiente como puede ser. Si puede hacerlo, es preferible. El modo de transmisión agrega mucha complejidad además de eso. La complejidad es principalmente interna y oculta, pero la idea principal es que no puede ser mejor / más rápido que la sencilla compresión o descompresión de un solo paso.

Gracias por una respuesta muy aclaratoria.
Rastreé una relación de compresión diferente en un orden diferente de mis datos. Sí, reutilizar el contexto frente a descartar no hace la diferencia, exactamente como dijiste. Lo siento, debería ser más cuidadoso e investigar más antes de presentar preguntas.
Tus comentarios son muy claros y muy explicativos. Creo que realmente es necesario agregarlo a los documentos. Especialmente parte de la diferencia entre la transmisión y la no transmisión: siempre pensé que la transmisión es más eficiente, ya que puede crear un diccionario mejor (aunque no está claro cómo se modifica el diccionario cuando los datos cambian hacia abajo en un archivo). Es muy importante comprender claramente que la transmisión es más o menos lo mismo que la compresión "basada en bloques". Por otro lado, la transmisión puede ser más eficiente, ya que maneja automáticamente el tamaño del fragmento. Estoy usando un tamaño de fragmento de 1 MB con un nivel de compresión predeterminado 3 y parece que no es suficiente para obtener una mejor compresión. Desde este punto de vista, la transmisión puede ser más eficiente en la relación de compresión, ya que determinará el tamaño del fragmento de manera más óptima. (¿¿¿Es esto correcto???)

la transmisión es prácticamente lo mismo que la compresión "basada en bloques"

No es exactamente "lo mismo".

Si corta los datos de entrada en trozos y los pasa de forma independiente a ZSTD_compressCCtx() , terminará con varios trozos comprimidos independientes. Cada fragmento comprimido es un _frame_ independiente. Se pueden descomprimir en cualquier orden, porque cada fotograma es independiente.

Si envía los mismos datos en un solo flujo, con ZSTD_compressStream() , sin fragmentar, terminará con un _ cuadro único_. Internamente, el marco se corta en bloques, sí, pero eso no importa, porque los bloques no son independientes. Para decodificar cualquier parte del marco, es necesario decodificar todo desde el principio.

En teoría, un solo fotograma debería comprimirse mejor que varios fotogramas independientes. Esto se debe a que cortar datos en varios fragmentos independientes hace que pierdan alguna oportunidad de compresión al comienzo de cada fragmento.
Sin embargo, los modos rápidos son simplemente compresores "probabilísticos", que hacen apuestas apresuradas para correr rápido. No todas las oportunidades son iguales y, a veces, seleccionar una oportunidad solo enmascara una mejor oportunidad posterior. Esto es muy específico de datos.
Por lo tanto, en algunos casos raros, puede suceder que cortar datos en fragmentos independientes termine siendo competitivo con un solo flujo.
Pero no apostaría por eso. En la mayoría de los casos, una sola transmisión debería ganar, aunque solo sea por muy poco.

¿Fue útil esta página
0 / 5 - 0 calificaciones