>백엔드 개발 >C++ >고성능 atoi 기능을 구현하기 위해 SIMD 명령어를 어떻게 사용할 수 있습니까?

고성능 atoi 기능을 구현하기 위해 SIMD 명령어를 어떻게 사용할 수 있습니까?

DDD
DDD원래의
2024-12-01 08:05:16716검색

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

atoi 함수의 SIMD 구현

소개:

atoi는 다음을 변환하는 함수입니다. 숫자 값에 대한 정수의 문자열 표현입니다. 이 문서에서는 SIMD 명령어를 사용하여 atoi를 구현하는 방법을 살펴봅니다.

알고리즘:

  1. 값 10^0, 10^1, ..을 사용하여 벡터 V를 초기화합니다. ., 10^N.
  2. 입력 문자열의 각 문자를 정수로 변환하여 저장합니다. 벡터 S.
  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 작업을 병렬로 수행할 수 있습니다. 작은 문자열과 혼합 문자 문자열을 처리하는 데에는 한계가 있지만 수치 계산을 위한 귀중한 기술로 남아 있습니다.

위 내용은 고성능 atoi 기능을 구현하기 위해 SIMD 명령어를 어떻게 사용할 수 있습니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.