Hub documentation

Deduplicación

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Deduplicación

Los repositorios habilitados con Xet utilizan segmentación definida por contenido (CDC) para eliminar duplicados a nivel de bytes (~64KB de datos, también denominados “chunk”). Cada chunk se identifica mediante un hash rodante que determina los límites de los chunks en función del contenido real del archivo, lo que lo hace resistente a inserciones o eliminaciones en cualquier parte del archivo. Cuando un archivo se sube a un repositorio respaldado por Xet mediante un cliente compatible con Xet, su contenido se divide en estos chunks de tamaño variable. Solo se conservan los chunks nuevos que no estén ya presentes en el almacenamiento de Xet; todo lo demás se descarta.

La deduplicación a nivel de fragmento también es lo que hace que las copias del lado del servidor sean instantáneas: hf buckets cp entre repositorios y cubos migra solo los hashes de contenido, sin volver a subir datos. Consulte Copiar archivos entre repositorios y cubos.

Cómo funciona la segmentación definida por contenido

Para entender el troceado definido por el contenido, imagine un archivo como un largo pasaje de texto. El sistema escanea los datos usando un hash rodante, una pequeña función matemática que se desplaza sobre los bytes. Cada vez que el hash alcanza un patrón especial, se coloca un límite de trozo en esa posición. Dado que los límites están determinados por el propio contenido (y no por posiciones fijas), las regiones de datos idénticas siempre producen los mismos trozos, incluso si el contenido circundante cambia.

¿Por qué no usar fragmentos de tamaño fijo?

Considere lo que ocurre cuando se inserta una pequeña cantidad de datos en el medio de un archivo. Con el troceado de tamaño fijo, cada límite de trozo posterior a la inserción se desplaza, invalidando todos los trozos aguas abajo, incluso aunque la mayor parte de los datos no haya cambiado:

Original file, fixed 6-byte chunks:

  |The qu|ick br|own fo|x jump|s over| the l|azy do|g     |
  chunk1  chunk2 chunk3 chunk4 chunk5 chunk6 chunk7 chunk8

Insert "very " before "lazy":

  |The qu|ick br|own fo|x jump|s over| the v|ery la|zy dog|
  chunk1  chunk2 chunk3 chunk4 chunk5 chunk6 chunk7 chunk8
                                       ~~~~~~ ~~~~~~ ~~~~~~
                                        3 chunks changed!

Aunque solo se insertaron 5 bytes, 3 de los 8 fragmentos cambiaron porque todas las fronteras posteriores a la edición se desplazaron 5 posiciones. En archivos reales con un tamaño de fragmento de 64 KB, una pequeña edición puede invalidar cientos de megabytes de fragmentos.

El chunking definido por el contenido mantiene estables las fronteras

Con CDC, los límites se colocan donde el contenido coincide con un patrón, no en intervalos fijos. Esto significa que una inserción solo afecta al fragmento donde ocurre la edición. Los fragmentos anteriores y posteriores permanecen idénticos:

Original file, content-defined chunks (boundaries marked by "|"):

  |The quick |brown fox |jumps over |the lazy dog|
    chunk 1     chunk 2    chunk 3     chunk 4

Insert "very " before "lazy":

  |The quick |brown fox |jumps over |the very lazy dog|
    chunk 1     chunk 2    chunk 3     chunk 4'
    (same)      (same)     (same)      (changed)

Solo 1 de 4 fragmentos cambió: el que contiene la edición. Los otros tres son idénticos byte a byte y se deduplican. Por eso CDC es tan eficaz para datos versionados: al actualizar un punto de control de un modelo o añadir filas a un conjunto de datos, solo es necesario subir y almacenar las porciones modificadas.

De Chunks a Almacenamiento

El pipeline completo de deduplicación funciona de la siguiente manera:

Cuando un archivo se divide en fragmentos, el hash de cada fragmento se comprueba contra lo que ya está almacenado. Esto ocurre en varios niveles: primero contra los fragmentos ya vistos en la sesión de carga actual, luego contra una caché local de metadatos de cargas anteriores y, finalmente, un subconjunto de fragmentos se comprueba contra todo el almacenamiento de Xet mediante una consulta global de deduplicación. Los fragmentos duplicados se omiten por completo. Los fragmentos nuevos se agrupan en bloques de 64 MB y se cargan. Cada bloque se almacena una vez en un almacén dirigido por contenido (CAS), con su hash como clave.

Ahorro de almacenamiento en la práctica

La recomendación actual del Hub es limitar los archivos a 200 GB. Con un tamaño de fragmento de 64 KB, un archivo de 20 GB tiene 312.500 fragmentos, muchos de los cuales no cambian de una versión a otra. Git LFS está diseñado para detectar únicamente que un archivo ha cambiado y almacenar la totalidad de esa revisión. Al realizar la deduplicación a nivel de fragmentos, el backend Xet permite almacenar solo el contenido modificado de un archivo (que podría ser de solo unos pocos KB o MB) y deduplica de forma segura los bloques compartidos entre repositorios. Para los archivos binarios grandes que se encuentran en los repositorios de Model y Dataset, esto proporciona mejoras significativas en los tiempos de transferencia de archivos.

Para más detalles, consulte las publicaciones de blog From Files to Chunks y From Chunks to Blocks, o el artículo Git is for Data de Low et al., que sirvió como punto de partida para XetHub antes de su adquisición por Hugging Face.

Update on GitHub