首页 > 后端开发 > C++ > 如何使用SIMD指令优化atoi功能?

如何使用SIMD指令优化atoi功能?

DDD
发布: 2024-12-30 04:13:09
原创
685 人浏览过

How Can SIMD Instructions Be Used to Optimize the atoi Function?

如何使用 SIMD 实现 atoi

在本文中,我们将探索实现 atoi 函数的算法,该函数将字符串表示形式转换为使用单指令多数据 (SIMD) 指令将整数转换为其数值。通过使用 SIMD,我们可以通过并行处理多个元素来实现显着的性能改进。

算法

建议的算法由以下步骤组成:

  1. 初始化长度为 N 的向量: 创建长度为 N 的向量,其中N 是您要支持的最大位数。使用表示 10 次幂的值(按降序排列)初始化向量(例如,[10^N, 10^(N-1), ..., 10^1])。
  2. 转换每个将缓冲区中的字符转换为整数: 将输入字符串中的每个字符转换为其对应的整数值并将其存储在另一个中向量。
  3. 将有效数字乘以 10 的幂: 从有效数字的向量中取出每个元素,并将其乘以 10 的幂向量中的相应元素。将结果求和这些乘法以获得字符串的数值。

具体来说,对于输入中的每个数字string:

  • 通过从 48 中减去其 ASCII 代码来提取数字值(0 到 9)。
  • 将数字值乘以相应的 10 次幂。
  • 将结果与之前计算的总和相加

实现注意事项

在 SIMD 代码中实现此算法时,我们可以利用 SIMD 指令固有的并行性来同时处理多个数字。代码应针对所使用的特定 SIMD 指令集(例如 SSE4.2、AVX2)进行优化。

潜在优化:

可以进一步优化该算法不需要单独的循环来将有效数字乘以 10 的幂。这可以通过使用称为“向量索引”的技术来实现与融合乘加。”这种技术允许我们在一条指令中执行索引和乘法,从而提高性能。

替代建议

正如 Peter Cordes 在评论中所建议的,最后两条加法异或指令的替代方法是使用 imul(整数乘法)指令。这有可能在代码大小和性能方面更加高效。

使用 Intel 语法在 GNU 汇编器中实现

这里是该算法的示例实现与 Intel 合作的 GNU 汇编程序语法:

.intel_syntax noprefix
.data
  .align 64
    ddqDigitRange: .byte  '0','9',0,0,0,0,0,0,0,0,0,0,0,0,0,0
    ddqShuffleMask:.byte  15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 
    ddqFactor1:    .word  1,10,100,1000, 1,10,100,1000  
    ddqFactor2:    .long  1,10000,100000000,0
.text    
_start:
   mov   esi, lpInputNumberString
   /* (**A**) indicate negative number in EDX */
   mov   eax, -1
   xor   ecx, ecx
   xor   edx, edx
   mov   bl,  byte ptr [esi]
   cmp   bl,  '-'
   cmove edx, eax
   cmp   bl,  '+'
   cmove ecx, eax
   sub   esi, edx
   sub   esi, ecx
   /* (**B**)remove leading zeros */
   xor   eax,eax               /* return value ZERO */
  remove_leading_zeros:
   inc   esi
   cmp   byte ptr [esi-1], '0'  /* skip leading zeros */
  je remove_leading_zeros
   cmp   byte ptr [esi-1], 0    /* catch empty string/number */
  je FINISH
   dec   esi
   /* check for valid digit-chars and invert from front to back */
   pxor      xmm2, xmm2         
   movdqa    xmm0, xmmword ptr [ddqDigitRange]
   movdqu    xmm1, xmmword ptr [esi]
   pcmpistri xmm0, xmm1, 0b00010100 /* (**C**) iim8=Unsigned bytes, Ranges, Negative Polarity(-), returns strlen() in ECX */
  jo FINISH             /* if first char is invalid return 0 - prevent processing empty string - 0 is still in EAX */
   mov al , '0'         /* value to subtract from chars */
   sub ecx, 16          /* len-16=negative to zero for shuffle mask */
   movd      xmm0, ecx
   pshufb    xmm0, xmm2 /* broadcast CL to all 16 BYTEs */
   paddb     xmm0, xmmword ptr [ddqShuffleMask] /* Generate permute mask for PSHUFB - all bytes < 0 have highest bit set means place gets zeroed */
   pshufb    xmm1, xmm0 /* (**D**) permute - now from highest to lowest BYTE are factors 10^0, 10^1, 10^2, ... */
   movd      xmm0, eax                         /* AL='0' from above */
   pshufb    xmm0, xmm2                        /* broadcast AL to XMM0 */
   psubusb   xmm1, xmm0                        /* (**1**) */
   movdqa    xmm0, xmm1
   punpcklbw xmm0, xmm2                        /* (**2**) */
   punpckhbw xmm1, xmm2
   pmaddwd   xmm0, xmmword ptr [ddqFactor1]    /* (**3**) */
   pmaddwd   xmm1, xmmword ptr [ddqFactor1]
   phaddd    xmm0, xmm1                        /* (**4**) */
   pmulld    xmm0, xmmword ptr [ddqFactor2]    /* (**5**) */
   pshufd    xmm1, xmm0, 0b11101110            /* (**6**) */
   paddd     xmm0, xmm1
   pshufd    xmm1, xmm0, 0b01010101            /* (**7**) */
   paddd     xmm0, xmm1
   movd      eax, xmm0
   /* negate if negative number */              
   add       eax, edx                          /* (**8**) */
   xor       eax, edx
  FINISH:
   /* EAX is return (u)int value */
登录后复制

结论

atoi 函数的这种优化的 SIMD 实现可以在处理大量数值数据时显着提高性能。通过利用 SIMD 指令的并行处理能力,我们可以实现更快的执行时间并更有效地处理数值计算。

以上是如何使用SIMD指令优化atoi功能?的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板