Расчет CRC32 для заполненного нулями буфера / файла - PullRequest
0 голосов
/ 27 октября 2018

Если я хочу вычислить значение CRC32 для большого количества последовательных нулевых байтов, есть ли формула с постоянным временем, которую я могу использовать, учитывая длину серии нулей? Например, если я знаю, что у меня все 1000 байтов заполнены нулями, есть ли способ избежать цикла с 1000 итерациями (просто пример, фактическое число нулей не ограничено ради этого вопроса)?

Ответы [ 2 ]

0 голосов
/ 27 октября 2018

Вы можете вычислить результат применения нулей n не за время O (1), а за время O (log n ).Это сделано в zlib's crc32_combine().Создается двоичная матрица, которая представляет операцию применения одного нулевого бита к CRC.Матрица 32x32 умножает 32-битный CRC на GF (2), где сложение заменяется на исключающее-или (^), а умножение заменяется на и (&), бит за битом.

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

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

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

Вам не нужно использовать инструкцию pclmulqdq, предложенную здесь в другом ответе, но это будет немного быстрееесли есть.Это не изменит O () операции.

0 голосов
/ 27 октября 2018

Если 1000 - это константа, предварительно вычисленная таблица из 32 значений, каждое из которых представляет каждый бит от CRC до 8000-й степени может быть использован. Набор матриц (один набор на байт CRC) может использоваться для работы с байтом за раз. Оба метода будут иметь постоянное время (фиксированное количество циклов) O (1).

Как прокомментировано выше, если 1000 не является константой, то можно использовать возведение в квадрат путем возведения в степень сложности O (log2 (n)) или комбинацию предварительно вычисленных таблиц для некоторого постоянного числа нулевых битов, например как 256, с последующим возведением в степень при помощи возведения в квадрат, так что последним шагом будет O (log2 (n% 256)).


Оптимизация в целом: для обычных данных с нулевыми и ненулевыми элементами на современном X86 с pclmulqdq (использует регистры xmm) может быть реализован быстрый crc32 (или crc16), хотя он составляет около 500 строк кода сборки , Документ Intel: crc с использованием pclmulqdq . Пример исходного кода для github fast crc16 . Для 32-битного CRC необходим другой набор констант. Если интересно, я преобразовал исходный код для работы с Visual Studio ML64.EXE (64-битный MASM) и создал примеры для 32-битных CRC с сдвигом влево и вправо, каждый с двумя наборами констант для двух наиболее популярных 32-битных полиномов CRC. (полис сдвига влево: crc32: 0x104C11DB7 и crc32c: 0x11EDC6F41, полис сдвига вправо немного перевернут).

...