Можно ли выполнить расчет CRC-32 в сплитах?

Я использую эту тривиальную функцию для вычисления контрольной суммы CRC данного файла:

long i, j = 0;
int k = 0;
uint crc = 0xFFFFFFFF;
FileInfo file_info = new FileInfo(file);
byte[] file_buffer = new byte[32768];

FileStream file_stream = new FileStream(@file, FileMode.Open);
while ((i = file_stream.Read(file_buffer, 0, file_buffer.Count())) > 0)
{
    for (j = 0; j < i; j++)
    {
        uint before = crc;
        k = (int)((crc ^ file_buffer[j]) & 0x000000FFL);
        uint after = (uint)((crc >> 8) & 0x00FFFFFFL) ^ crc32_table[k];
        crc = after;
        uint test = (uint)((crc << 8) & 0x00FFFFFFL) ^ crc32_table[k];
        MessageBox.Show((~crc).ToString("X"));
    }
}
file_stream.Close();
return ~crc;

мой вопрос таков: скажем, у меня есть большой файл, скажем, 100MB. Есть ли связь между КПР-32 начисления первых 50 МБ и последний 50МБ и КПР-32 расчет 100МБ файл?

причина, по которой я спрашиваю, в том, что у меня есть очень большие файлы (~10 ГБ плюс-минус), которые требуют некоторого времени для генерации, но пока они генерируются, большинство частей остаются статическими, однако части в середине (известная точка) и прямо в начале (заголовок, также известная часть/длина). Вычисление контрольной суммы CRC-32 файла 10GB занимает довольно много времени, поэтому мне было интересно, есть ли способ сделать это кусками?

3 ответов


Это is действительно возможно распараллелить вычисление CRC-32, но детали грязные, и мне нужно потратить около дня, чтобы придумать код.

давайте рассмотрим базовый алгоритм CRC, где нет отрицания и нет реверсирования битов.

для строки байтов, которую вы хотите вычислить CRC, назовем ее сообщением. Основная идея заключается в том, что вы рассматриваете сообщение как многочлен в GF (2), и вычислить остаток по модулю полинома CRC.

основной алгоритм CRC является аддитивным/линейным. Если у вас есть два сообщения a и b одинаковой длины, то CRC(A XOR b) = CRC(a) XOR CRC(b).

кроме того, если вы поместите сообщение с правой стороны с n нулями, новый CRC будет старым CRC times x^N mod многочлен CRC.

со всем сказанным, единственный способ решить вашу проблему-это действительно понять математику алгоритма CRC и написать свой собственный код. Вот длинное, но очень полное объяснение CRCs:http://www.ross.net/crc/download/crc_v3.txt


да. См.crc32_combine() на zlib для примера.


это уравнение является ключевым:

CRC(a XOR b) == CRC(a) XOR CRC(b)

Предположим, вы хотите вычислить CRC следующее сообщение:

"Always desire to learn something useful."

существуют функции для вычисления CRC как:

crc_join(crc_part1("Always desire to lea"),
         crc_part2("rn something useful."))

если crc_part1 и crc_part2 нули pad () свои аргументы, как показано, crc_join это просто XOR.

crc_part1 = crc("Always desire to lea")
crc_part2 = crc("rn something useful.")

нули могут быть учтены в crc_part1 с таблицами подстановок. Ведущие нули можно игнорировать в crc_part2.

ссылки:

  1. высокоскоростная параллельная архитектура для программного обеспечения CRC
    Youngju. Делай, Сон Рок. Юн, Тэкю. Ким, Кван Юи. Пьюн и Син-Чонг. Парк
  2. https://en.wikipedia.org/wiki/Cyclic_redundancy_check