_mm_crc32_u64定义不清(_mm_crc32_u64 poorly defined)

2019-08-18 19:23发布

世界为什么_mm_crc32_u64(...)这样定义呢?

unsigned int64 _mm_crc32_u64( unsigned __int64 crc, unsigned __int64 v );

该“CRC32”指令总是积累了32位CRC, 从来没有一个64位CRC(这是,毕竟,CRC32不CRC64)。 如果机器指令CRC32 恰好有一个64位目的地操作数,高32位被忽略,并用0填充的上完成,所以没有使用到EVER有一个64位的目的地。 我明白了为什么英特尔允许的指令(一致性)64位目的地操作数,但如果我想快速处理数据,我希望有一个源操作数尽可能大(即64位,如果我有剩多少数据,对于尾端),并总是32位目的地操作数小。 但内部函数不允许一个64位源和32位目的地。 注意其他内部函数:

unsigned int _mm_crc32_u8 ( unsigned int crc, unsigned char v ); 

的类型的“CRC”是不是8位的类型,也不是返回类型,它们是32位。 为什么没有

unsigned int _mm_crc32_u64 ( unsigned int crc, unsigned __int64 v );

? 英特尔指令支持这一点, 就是最有意义的内在。

有没有人有移植的代码(Visual Studio和GCC)实施后的内在? 谢谢。 我的猜测是这样的:

#define CRC32(D32,S) __asm__("crc32 %0, %1" : "+xrm" (D32) : ">xrm" (S))

海湾合作委员会,并

#define CRC32(D32,S) __asm { crc32 D32, S }

对于VisualStudio中。 不幸的是我的约束是如何起作用知之甚少,并与语法和汇编级编程的语义一点经验。

小编辑:请注意,我定义的宏:

#define GET_INT64(P) *(reinterpret_cast<const uint64* &>(P))++
#define GET_INT32(P) *(reinterpret_cast<const uint32* &>(P))++
#define GET_INT16(P) *(reinterpret_cast<const uint16* &>(P))++
#define GET_INT8(P)  *(reinterpret_cast<const uint8 * &>(P))++


#define DO1_HW(CR,P) CR =  _mm_crc32_u8 (CR, GET_INT8 (P))
#define DO2_HW(CR,P) CR =  _mm_crc32_u16(CR, GET_INT16(P))
#define DO4_HW(CR,P) CR =  _mm_crc32_u32(CR, GET_INT32(P))
#define DO8_HW(CR,P) CR = (_mm_crc32_u64((uint64)CR, GET_INT64(P))) & 0xFFFFFFFF;

注意最后的宏语句多么不同。 缺乏统一的肯定和指示是内在尚未合理确定。 虽然没有必要把在显式(uint64)在最后一个宏铸造,它是隐含的,确实会发生。 拆卸生成的代码的代码显示两个施放32-> 64和64-> 32,这两者都是不必要的。

换句话说,它是_mm_crc32_u64 _mm_crc64_u64 ,但他们已经实现了它,仿佛它是后者。

如果我能得到的定义CRC32上述正确的,那么我想改变我的宏

#define DO1_HW(CR,P) CR = CRC32(CR, GET_INT8 (P))
#define DO2_HW(CR,P) CR = CRC32(CR, GET_INT16(P))
#define DO4_HW(CR,P) CR = CRC32(CR, GET_INT32(P))
#define DO8_HW(CR,P) CR = CRC32(CR, GET_INT64(P))

Answer 1:

有没有人有移植的代码(Visual Studio和GCC)实施后的内在? 谢谢。

我的朋友和我写了一个C ++上证所内部函数的包装,其包含64位的src CRC32指令的更优选的使用。

http://code.google.com/p/sse-intrinsics/

见i_crc32()指令。 (遗憾的是还有更瑕疵与其他指令Intel的SSE固有的规格,请参阅此页面为有缺陷的内在设计的更多示例)



Answer 2:

真正提供的4个内在功能做到让英特尔的所有可能的用途定义CRC32指令。 该指令输出总是32位,因为指令是硬编码为使用特定的32位CRC多项式。 但是,该指令允许您的代码输入数据8,16,32,或64位一次仅进给它。 一次处理64位应最大化吞吐量。 一次处理32位是如果仅限于32位构建,你能做的最好的。 在一个时间处理8或16位可以简化代码逻辑如果输入字节数是奇数还是与否的4/8的倍数。

#include <stdio.h>
#include <stdint.h>
#include <intrin.h>

int main (int argc, char *argv [])
    {
    int index;
    uint8_t *data8;
    uint16_t *data16;
    uint32_t *data32;
    uint64_t *data64;
    uint32_t total1, total2, total3;
    uint64_t total4;
    uint64_t input [] = {0x1122334455667788, 0x1111222233334444};

    total1 = total2 = total3 = total4 = 0;
    data8  = (void *) input;
    data16 = (void *) input;
    data32 = (void *) input;
    data64 = (void *) input;

    for (index = 0; index < sizeof input / sizeof *data8; index++)
        total1 = _mm_crc32_u8 (total1, *data8++);

    for (index = 0; index < sizeof input / sizeof *data16; index++)
        total2 = _mm_crc32_u16 (total2, *data16++);

    for (index = 0; index < sizeof input / sizeof *data32; index++)
        total3 = _mm_crc32_u32 (total3, *data32++);

    for (index = 0; index < sizeof input / sizeof *data64; index++)
        total4 = _mm_crc32_u64 (total4, *data64++);

    printf ("CRC32 result using 8-bit chunks: %08X\n", total1);
    printf ("CRC32 result using 16-bit chunks: %08X\n", total2);
    printf ("CRC32 result using 32-bit chunks: %08X\n", total3);
    printf ("CRC32 result using 64-bit chunks: %08X\n", total4);
    return 0;
    }


文章来源: _mm_crc32_u64 poorly defined
标签: c sse crc crc32 sse4