首頁 > 後端開發 > C++ > 如何使用SIMD指令優化atoi功能?

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

DDD
發布: 2024-12-30 04:13:09
原創
701 人瀏覽過

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

如何使用SIMD 實作atoi

在本文中,我們將探討實作atoi 函數的演算法,該函數將字串表示形式轉換為使用單指令多重資料(SIMD) 指令將整數轉換為其數值。透過使用 SIMD,我們可以透過並行處理多個元素來實現顯著的效能改進。

演算法

建議的演算法由下列步驟組成:

  1. 初始化長度為N 的向量:
  2. 初始化長度為N 的向量: 建立長度為N 的向量,其中N 是您要支援的最大位數。使用表示 10 次方的值(按降序排列)初始化向量(例如,[10^N, 10^(N-1), ..., 10^1])。
  3. 轉換每個將緩衝區中的字元轉換為整數:
  4. 將輸入字串中的每個字元轉換為其對應的整數值並將其儲存在另一個中向量。
  5. 將有效數字乘以 10 的冪:
從有效數字的向量中取出每個元素,並將其乘以 10 的冪向量中的對應元素。將結果求和這些乘法以獲得字串的數值。

    具體來說,對於輸入中的每個數字string:
  • 透過從 48 中減去其 ASCII 程式碼來提取數字值(0 到 9)。
  • 將數字值乘以對應的 10 次方。
將結果與先前計算的總和相加

實現注意事項

在SIMD 程式碼中實現此演算法時,我們可以實現此演算法利用SIMD 指令固有的並行性來同時處理多個數字。程式碼應針對所使用的特定 SIMD 指令集(例如 SSE4.2、AVX2)進行最佳化。

潛在最佳化:

可以進一步最佳化此演算法不需要單獨的迴圈來將有效數字乘以 10 的冪次方。這可以透過使用稱為“向量索引”的技術來實現與融合乘加。 「這種技術允許我們在一條指令中執行索引和乘法,從而提高效能。

替代建議

正如Peter Cordes 在評論中所建議的,最後兩個加法異或指令的替代方法是使用imul(整數乘法)指令。的範例實作與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
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板