Итак, у меня есть конструкция, которая включает контрольные суммы CRC32C, чтобы гарантировать, что данные не были повреждены. Я решил использовать CRC32C, потому что у меня могут быть как версия программного обеспечения, так и версия с аппаратным ускорением, если компьютер работает на опорах SSE 4.2Внедрение CRC32C SSE 4.2 в программном обеспечении
Я собираюсь с помощью руководства разработчика Intel (vol 2A), которое, как представляется, обеспечивает алгоритм, лежащий в основе инструкции crc32
. Тем не менее, у меня мало шансов. руководство разработчика Intel говорит следующее:
BIT_REFLECT32: DEST[31-0] = SRC[0-31]
MOD2: Remainder from Polynomial division modulus 2
TEMP1[31-0] <- BIT_REFLECT(SRC[31-0])
TEMP2[31-0] <- BIT_REFLECT(DEST[31-0])
TEMP3[63-0] <- TEMP1[31-0] << 32
TEMP4[63-0] <- TEMP2[31-0] << 32
TEMP5[63-0] <- TEMP3[63-0] XOR TEMP4[63-0]
TEMP6[31-0] <- TEMP5[63-0] MOD2 0x11EDC6F41
DEST[31-0] <- BIT_REFLECT(TEMP6[31-0])
Теперь, насколько я могу сказать, что я сделал все, вплоть до строки, начинающейся TEMP6
правильно, но я думаю, что может быть либо непонимание полиномиального деления, или реализации это неправильно. Если мое понимание верное, 1/1 mod 2 = 1
, 0/1 mod 2 = 0
, и оба деления на ноль не определены.
Я не понимаю, как будет работать двоичное деление с 64-битными и 33-битными операндами. Если SRC
- 0x00000000
, а DEST
- 0xFFFFFFFF
, TEMP5[63-32]
- все будут биты набора, а TEMP5[31-0]
- все разряженные разряды.
Если бы я был использовать биты из TEMP5
в числителе, было бы 30 делений на ноль, как полином 11EDC6F41
только 33 битов длиной (и так преобразования его в 64-битовое беззнаковое целое оставляет верхние 30 бит unset), и поэтому знаменатель не установлен на 30 бит.
Однако, если бы я использовал полином в качестве числителя, нижние 32 бита TEMP5
не заданы, в результате чего делятся на нуль, а верхние 30 бит результата будут равны нулю, так как верхние 30 бит числителя будет 0, 0/1 mod 2 = 0
.
Я не понимаю, как это работает? Просто что-то пропало? Или Intel отказалась от некоторых важных шагов в своей документации?
Причина, по которой я пришел к руководству разработчика Intel, по тому, что, по-видимому, был использован им, заключается в том, что они использовали 33-битный полином, и я хотел сделать вывод идентичным, чего не было, когда я использовал 32- битовый многочлен 1EDC6F41
(показать ниже).
uint32_t poly = 0x1EDC6F41, sres, crcTable[256], data = 0x00000000;
for (n = 0; n < 256; n++) {
sres = n;
for (k = 0; k < 8; k++)
sres = (sres & 1) == 1 ? poly^(sres >> 1) : (sres >> 1);
crcTable[n] = sres;
}
sres = 0xFFFFFFFF;
for (n = 0; n < 4; n++) {
sres = crcTable[(sres^data) & 0xFF]^(sres >> 8);
}
Приведенные выше код производит 4138093821
в качестве выходного сигнала, а crc32
опкода производит 2346497208
с использованием входа 0x00000000
.
Извините, если это плохо написано или непонятно местами, для меня это довольно поздно.
Для тех, кто использует Delphi, я [написал код с открытым исходным кодом] (http://blog.synopse.info/post/2014/05/25/New-crc32c%28%29-function-using-optimized -asm и SSE-4.2), используя новую командную инструкцию 'crc32', если она доступна, и быстрый x86 asm или чистый код pascal (с использованием предварительно вычисленных таблиц), если SSE 4.2 недоступен. Наивная развернутая версия работает со скоростью 330 Мбайт/с, оптимизированная развернутая x86 asm работает со скоростью 1,7 ГБ/с, а аппаратное обеспечение SSE 4.2 обеспечивает потрясающую скорость 3,7 ГБ/с (на обеих платформах Win32 и Win64). –