¿Cómo implementar CRC32 aprovechando las instrucciones específicas de Intel?

Intel tiene una instrucción CRC32 específica disponible en el conjunto de instrucciones SSE4.2. ¿Cómo puedo aprovechar esta instrucción para acelerar los cálculos de CRC32?

En primer lugar, la instrucción CRC32 de Intel sirve para calcular CRC-32C (es decir, utiliza un polinomio diferente al de CRC32 regular. Mire la entrada de Wikipedia CRC32 )

Para usar la aceleración de hardware de Intel para CRC32C usando gcc , puede:

  1. Lenguaje ensamblador en línea en código C a través de la statement asm
  2. Utilice intrínsecos _mm_crc32_u8 , _mm_crc32_u16 , _mm_crc32_u32 o _mm_crc32_u64 . Consulte la Guía de Intel Intrinsics para obtener una descripción de los del comstackdor icc Intel, pero gcc también los implementa.

Así es como lo haría con __mm_crc32_u8 que toma un byte a la vez, usar __mm_crc32_u64 proporcionaría una mejora adicional en el rendimiento, ya que toma 8 bytes a la vez.

 uint32_t sse42_crc32(const uint8_t *bytes, size_t len) { uint32_t hash = 0; size_t i = 0; for (i=0;i 

Para comstackr esto necesitas pasar -msse4.2 en CFLAGS . Al igual que gcc -g -msse4.2 test.c contrario se quejará de una undefined reference to _mm_crc32_u8 .

Si desea volver a una implementación de C simple si la instrucción no está disponible en la plataforma donde se ejecuta el ejecutable, puede usar el atributo ifunc de GCC. Me gusta

 uint32_t sse42_crc32(const uint8_t *bytes, size_t len) { /* use _mm_crc32_u* here */ } uint32_t default_crc32(const uint8_t *bytes, size_t len) { /* pure C implementation */ } /* this will be called at load time to decide which function really use */ /* sse42_crc32 if SSE 4.2 is supported */ /* default_crc32 if not */ static void * resolve_crc32(void) { __builtin_cpu_init(); if (__builtin_cpu_supports("sse4.2")) return sse42_crc32; return default_crc32; } /* crc32() implementation will be resolved at load time to either */ /* sse42_crc32() or default_crc32() */ uint32_t crc32(const uint8_t *bytes, size_t len) __attribute__ ((ifunc ("resolve_crc32"))); 

Vea esta respuesta para las implementaciones rápidas de hardware y software de CRC-32C. La implementación del hardware ejecuta efectivamente tres instrucciones crc32 en paralelo para la velocidad.