ホームページ >バックエンド開発 >C++ >SIMD 命令を使用して高性能の atoi 関数を実装するにはどうすればよいですか?

SIMD 命令を使用して高性能の atoi 関数を実装するにはどうすればよいですか?

DDD
DDDオリジナル
2024-12-01 08:05:16717ブラウズ

How Can SIMD Instructions Be Used to Implement a High-Performance atoi Function?

atoi 関数の SIMD 実装

はじめに:

atoi は、次の変換を行う関数です。整数をその数値に変換する文字列表現。この記事では、SIMD 命令を使用して atoi を実装する方法について説明します。

アルゴリズム:

  1. ベクトル V を値 10^0、10^1、... で初期化します。 ., 10^N.
  2. 入力文字列の各文字を整数に変換して格納します
  3. S の各要素と V の対応する要素を乗算し、その結果を新しいベクトル P に格納します。
  4. P に対して一連の水平方向の加算と乗算を実行して、最終結果。

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             /* if first char is invalid return 0 - prevent processing empty string - 0 is still in EAX */
   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 */

SIMD 実装の利点:

  • 大きな数値文字列を処理するパフォーマンスの向上。
  • x86 および x86-64 で実現可能
  • 複数の atoi 操作を同時にサポートします。

制限事項:

  • 特定の SSE4.2 命令が必要です。
  • 小さな文字列や混合文字列には適さない場合があります

結論:

atoi の SIMD 実装は、従来の方法と比較して大きな整数文字列の処理を大幅に高速化します。このアルゴリズムは x86 および x86-64 アーキテクチャ向けに最適化されており、複数の atoi 操作を並行して実行できます。小さい文字列や文字が混在する文字列の処理には制限がありますが、数値計算には依然として価値のある手法です。

以上がSIMD 命令を使用して高性能の atoi 関数を実装するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。