Assembly 有效校验和为8×;使用SSE4.1的16位整数向量

Assembly 有效校验和为8×;使用SSE4.1的16位整数向量,assembly,x86,sse,checksum,micro-optimization,Assembly,X86,Sse,Checksum,Micro Optimization,我使用8个组件的彩色像素,每个颜色组件有16位深度。比如说,CMYK+4个额外的专色,但这并不重要:重要的是,每种颜色都可以表示为word的数组[0..7] 在我们讨论的特定应用程序中,使用32位的“代理”更方便,实际上,使用32位的校验和计算颜色是一种特定的方式。当然,我会处理一些不太可能的情况,即两个相同的校验和仍然代表不同的颜色。这样做的目的是尽可能少地遇到这种情况,也就是说,校验和应该尽可能随机,而且它们的计算速度必须非常快。我可以使用英特尔/AMDSIMD直到SSE 4.1 我的想法如

我使用8个组件的彩色像素,每个颜色组件有16位深度。比如说,CMYK+4个额外的专色,但这并不重要:重要的是,每种颜色都可以表示为word的
数组[0..7]

在我们讨论的特定应用程序中,使用32位的“代理”更方便,实际上,使用32位的校验和计算颜色是一种特定的方式。当然,我会处理一些不太可能的情况,即两个相同的校验和仍然代表不同的颜色。这样做的目的是尽可能少地遇到这种情况,也就是说,校验和应该尽可能随机,而且它们的计算速度必须非常快。我可以使用英特尔/AMD
SIMD
直到
SSE 4.1

我的想法如下:

  • 将不同的预定义常量(最好是素数)添加到每个组件,以消除空组件
  • 通过乘以不同的素数对这些分量进行加权
  • 求结果双字的和
  • 大概是这样的:

    movdqa xmm0, COLORPIXEL  // the color to get the checksum from
    movdqa xmm1, WEIGHTCONST // e.g. (32749, 32647, 32573, 32503, 32719, 32633, 32569, 32497)
    paddw xmm0, ADDCONST     // e.g. (32687, 32587, 32531, 32441, 32653, 32579, 32507, 32429)
    pmaddwd xmm1, xmm0
    phaddd xmm1, xmm1
    phaddd xmm1, xmm1
    movd eax, xmm1           // result in 32 bits register
    
    这段代码似乎足够好,速度也相当快,但更好的想法是受欢迎的。我以前从未使用过校验和,因此很有可能使用传统的解决方案,例如数据传输中使用的不同CRC是更好的选择

    注:

  • 一种颜色通常(但不是强制性的)只有几个非零分量,通常高达3
  • 非常罕见的是,一个非零点分量(即索引为4或更高)与一个以上的其他非零分量配对
  • 专色本身比CMYK颜色(索引为0到3)更为罕见
  • 65535(全色调)的值可能比其他随机值更频繁

  • phaddd
    需要2次洗牌+1次
    paddd
    uop;切勿将其用于有效的水平求和。你能用x86CRC32C指令做2个qwords吗?特别是如果您希望结果是整数reg,而不是XMM。我忘了如果这些是在SSE4.1之后引入的,可能是在与SSE4.2相同的CPU中。有关有效整数和的信息,请参阅。是否确实需要返回EAX中的结果?如果要传输它,难道不想将它存储到内存中的缓冲区中吗?对于
    pmaddwd
    ,也要使用内存源操作数(除非您可以将向量常量的负载从循环中提升出来)。只是为了确定,“SIMD到SSE 4.1”意味着绝对没有CRC32指令?而且没有AES?SSE4.2+CRC32C+AES会给您提供英特尔Nehalem/AMD推土机的基线要求。这些CPU可以追溯到2008/2010年,它们本身已经过时。但Core2和K10(AMD Phenom II)的速度甚至更慢,幅度很大。不过,我想你会想为Skylake/Ryzen调音,因为大多数电脑都会使用Skylake/Ryzen。(Skylake调优对Haswell来说并不坏;差别很小;只是一些UOP可以在更多端口上运行,例如SIMD整数移位、加法和乘法。)@PeterCordes AES是Westmile。一个接一个。