Из Википедии, бесплатной энциклопедии
Перейти к навигации Перейти к поиску

Прокатки хэш (также известная как рекурсивное хеширование или прокатка контрольная сумма) является хэш - функцией , где входным хешируются в окне , которое проходит через вход.

Несколько хеш-функций позволяют очень быстро вычислять скользящий хэш - новое значение хеш-функции быстро вычисляется с учетом только старого значения хеш-функции, старого значения, удаленного из окна, и нового значения, добавляемого в окно - аналогично тому, как Функция скользящего среднего может быть вычислена намного быстрее, чем другие фильтры нижних частот.

Одним из основных приложений является алгоритм поиска строки Рабина – Карпа , который использует скользящий хеш, описанный ниже. Еще одно популярное приложение - программа rsync , которая в качестве скользящего хеша использует контрольную сумму на основе adler-32 Марка Адлера . Сетевая файловая система с низкой пропускной способностью (LBFS) использует отпечаток Рабина в качестве скользящего хэша. FastCDC (Fast Content-Defined Chunking) использует эффективный для вычислений отпечаток Gear в качестве скользящего хэша.

В лучшем случае скользящие хеш-значения попарно независимы [1] или строго универсальны . Например, они не могут быть независимыми по трем направлениям .

Полиномиальный скользящий хеш [ править ]

Строка алгоритм поиска Рабин-Карп часто объясняется использование подвижной хэш - функции , которая использует только умножения и сложения:

,

где - константа, и - входные символы (но эта функция не является отпечатком Рабина , см. ниже).

Чтобы избежать манипулирования огромными значениями, все вычисления производятся по модулю . Выбор и имеет решающее значение для получения хорошего хеширования; см. линейный конгруэнтный генератор для более подробного обсуждения.

Удаление и добавление символов просто включает добавление или вычитание первого или последнего члена. Чтобы сдвинуть все символы на одну позицию влево, необходимо умножить всю сумму на . Чтобы сдвинуть все символы на одну позицию вправо, нужно разделить всю сумму на . Обратите внимание, что в арифметике по модулю можно выбрать множитель, обратный, на который можно умножить, чтобы получить результат деления без фактического выполнения деления.

Отпечаток Рабина [ править ]

Отпечатков пальцев Рабина еще один хэш, который также интерпретирует входные данные в виде полинома, но над полем Галуа GF (2) . Вместо того, чтобы рассматривать ввод как полином из байтов, он рассматривается как полином из битов, и вся арифметика выполняется в GF (2) (аналогично CRC32 ). Хеш - это результат деления этого многочлена на неприводимый многочлен над GF (2). Можно обновить отпечаток Рабина, используя только входной и выходной байты, что фактически делает его скользящим хешем.

Поскольку он имеет того же автора, что и алгоритм поиска строки Рабина – Карпа, который часто объясняется другим, более простым скользящим хешем, и поскольку этот более простой скользящий хеш также является полиномом, оба скользящих хеш-значения часто ошибочно принимают друг за друга. Программное обеспечение для резервного копирования restic использует отпечаток Рабина для разделения файлов с размером большого двоичного объекта от 512 байт до 8 МБ. [2]

Циклический полином [ править ]

Хеширование с помощью циклического полинома [3], иногда называемого Бужашем, также простое, но его преимущество заключается в том, что он позволяет избежать умножений, используя вместо этого сдвиг в форме бочки . Это форма хеширования табуляции : предполагается, что в интервале есть некоторая хеш-функция от символов до целых чисел . Эта хеш-функция может быть просто массивом или хеш-таблицей, отображающей символы в случайные целые числа. Пусть функция будет циклическим двоичным вращением (или круговым сдвигом ): она поворачивает биты на 1 влево, сдвигая последний бит в первую позицию. Например, . Позвольте быть побитовым исключающим или . Хеш-значения определены как

где умножение на степень двойки может быть выполнено двоичным сдвигом. Результат - число в .

Вычисление хеш-значений в скользящем режиме выполняется следующим образом. Позвольте быть предыдущим значением хеш-функции. Поворот один раз: . Если это символ должен быть удален, вращать его раз: . Затем просто установите

где новый персонаж.

Хеширование с помощью циклических многочленов является строго универсальным или попарно независимым: просто сохраните первые биты. То есть взять результат и отбросить все последовательные биты. [1] На практике это достигается целочисленным делением .

Нарезка на основе содержимого с использованием скользящего хеша [ править ]

Одним из интересных вариантов использования скользящей хеш-функции является то, что она может создавать динамические блоки на основе содержимого потока или файла. Это особенно полезно, когда требуется отправить по сети только измененные фрагменты большого файла, а простое добавление байтов в начале файла приведет к обновлению всех окон фиксированного размера, в то время как на самом деле только первые "кусок" был изменен.

Самый простой подход к вычислению динамических фрагментов - это вычисление скользящего хэша, и если он соответствует шаблону (например, все младшие N бит - нули), то это граница фрагмента. Такой подход гарантирует, что любое изменение в файле повлияет только на его текущий и, возможно, следующий фрагмент, но ни на что другое.

Когда границы известны, блоки необходимо сравнить по их хеш-значениям, чтобы определить, какой из них был изменен и нуждается в передаче по сети. [4] Программа резервного копирования Attic использует алгоритм Buzhash с настраиваемым диапазоном размеров фрагментов для разделения потоков файлов. [5]

Нарезка на основе содержимого с использованием скользящей суммы [ править ]

Несколько программ, включая gzip (с --rsyncableопцией) и rsyncrypto, выполняют нарезку на основе содержимого на основе этой конкретной (невзвешенной) скользящей суммы: [6]

где

  • представляет собой сумму 8196 последовательных байтов, заканчивающихся байтом (требуется 21 бит памяти),
  • это байт файла,
  • представляет собой «хеш-значение», состоящее из нижних 12 битов .

Сдвиг окна на один байт просто включает добавление нового символа к сумме и вычитание самого старого символа (уже не находящегося в окне) из суммы.

Везде, где эти программы разрезают файл между и . Такой подход гарантирует, что любое изменение в файле повлияет только на его текущий и, возможно, следующий фрагмент, но не на другой фрагмент.

Отпечаток устройства Gear и алгоритм фрагментации на основе контента FastCDC [ править ]

Алгоритм Content-Defined Chunking (CDC) должен вычислять хэш-значение потока данных побайтно и разбивать поток данных на части, когда хеш-значение соответствует заранее заданному значению. Однако побайтовое сравнение строки приведет к значительным накладным расходам на вычисления. FastCDC [7] предлагает новый и эффективный подход Content-Defined Chunking. Он использует алгоритм быстрого хеширования Gear [8], пропускающий минимальную длину, нормализуя распределение размеров фрагментов и, наконец, что не менее важно, каждый раз прокручивая два байта для ускорения алгоритма CDC, что может обеспечить примерно в 10 раз более высокую пропускную способность. чем подход CDC, основанный на Рабине. [9]

Базовый псевдокод версии представлен следующим образом:

алгоритм FastCDC input: data buffer src , длина данных n , вывод: точка отсечения i  MinSize ← 2 КБ // минимальный размер фрагмента 2 КБ MaxSize ← 64 КБ // максимальный размер фрагмента 64 КБ fp0  iMinSize  Mask0x0000d93003530000LL  // размер буфера меньше минимального размера блока если  nMinSize,  то  вернуть  n,  если  nMaxSize,  то  nMaxSize     while  i < n  do  fp ← ( fp << 1) + Gear [ src [ i ]] if  ! ( fp & Mask ) тогда  вернуть  i    вернуть  я

Где Gear array - это предварительно рассчитанный массив хеширования. Здесь FastCDC использует алгоритм хеширования Gear, который может быстро вычислять результаты скользящего хеширования и сохранять равномерное распределение результатов хеширования, как у Рабина. По сравнению с традиционным алгоритмом хеширования Рабина, он обеспечивает гораздо более высокую скорость. Эксперименты показывают, что при сегментировании потока данных он может генерировать почти такое же распределение размеров блоков за гораздо более короткое время (около 1/10 фрагментов на основе рабина [9] ).

Вычислительная сложность [ править ]

Все скользящие хеш-функции линейны по количеству символов, но их сложность в зависимости от длины окна ( ) варьируется. Скручивающийся хеш Рабина – Карпа требует умножения двухбитовых чисел, целочисленное умножение - в . [10] Хеширование диаграмм циклическими многочленами может выполняться за линейное время. [1]

Программное обеспечение [ править ]

  • Rollinghashcpp - это бесплатная реализация на C ++ нескольких скользящих хеш-функций.
  • Rollinghashjava - это Java-реализация скользящих хеш-функций с лицензией Apache.

См. Также [ править ]

  • MinHash
  • шинглинг

Внешние ссылки [ править ]

  • MIT 6.006: Введение в алгоритмы 2011 - Конспект лекций - скользящий хеш

Сноски [ править ]

  1. ^ a b c Даниэль Лемир, Оуэн Кейзер: Рекурсивное хеширование n -грамм в лучшем случае попарно независимо, Computer Speech & Language 24 (4), страницы 698–710, 2010. arXiv: 0705.4676 .
  2. ^ «Ссылки - документация restic 0.9.0» . restic.readthedocs.io . Проверено 24 мая 2018 .
  3. ^ Джонатан Д. Коэн, Рекурсивные функции хеширования для n -грамм, ACM Trans. Инф. Syst. 15 (3), 1997.
  4. Хорват, Адам (24 октября 2012 г.). «Скользящий хеш Рабина Карпа - блоки динамического размера на основе хешированного содержимого» .
  5. ^ «Структуры данных и форматы файлов - документация Borg - Deduplicating Archiver 1.1.5» . borgbackup.readthedocs.io . Проверено 24 мая 2018 .
  6. ^ «Алгоритм Rsyncrypto» .
  7. ^ Ся, Вэнь; Чжоу, Юкунь; Цзян, Хун; Фэн, Дэн; Хуа Ю; Ху Юйчун; Лю, Цин; Чжан, Юйчэн. «FastCDC: быстрый и эффективный подход к разделению на блоки с определением содержимого для дедупликации данных» . USENIX . Проверено 24 июля 2020 .
  8. ^ Ся, Вэнь; Цзян, Хун; Фэн, Дэн; Тиан, Лэй; Фу, Мин; Чжоу, Юкун (2014). «Ddelta: основанный на дедупликации подход быстрого дельта-сжатия». Оценка производительности . 79 : 258–272. DOI : 10.1016 / j.peva.2014.07.016 . ISSN 0166-5316 . 
  9. ^ а б Ся, Вэнь; Цзоу, Сянъюй; Цзян, Хун; Чжоу, Юкунь; Лю, Чуаньи; Фэн, Дэн; Хуа Ю; Ху Юйчун; Чжан, Юйчэн (16.06.2020). «Дизайн быстрого разбиения на блоки с определением содержимого для систем хранения на основе дедупликации данных» . Транзакции IEEE в параллельных и распределенных системах . 31 (9): 2017–2031. DOI : 10.1109 / TPDS.2020.2984632 . S2CID 215817722 . Проверено 22 июля 2020 . 
  10. ^ М. Furer, Faster целочисленное умножение в: STOC '07, 2007, стр 57-66..