首页  >  文章  >  后端开发  >  有没有更快的方法将 IPv4 地址从字符串转换为整数?

有没有更快的方法将 IPv4 地址从字符串转换为整数?

Patricia Arquette
Patricia Arquette原创
2024-11-17 07:35:04531浏览

Is There a Faster Way to Convert IPv4 Addresses from Strings to Integers?

从字符串转换 IPv4 地址的有效替代方案

问:提高从字符串解析 IPv4 地址的速度

从字符串解析 IPv4 地址的现有解决方案可能很慢,限制了吞吐量。有更快的方法或可行的替代方案吗?

A:SSE4.1 的矢量化解决方案

概述

为了最大限度地提高解析性能,利用 SSE4.1 指令的矢量化解决方案具有显着的速度优势:

代码

__m128i shuffleTable[65536];    //can be reduced 256x times, see @IwillnotexistIdonotexist

UINT32 MyGetIP(const char *str) {
    __m128i input = _mm_lddqu_si128((const __m128i*)str);   //"192.167.1.3"
    input = _mm_sub_epi8(input, _mm_set1_epi8('0'));        //1 9 2 254 1 6 7 254 1 254 3 208 245 0 8 40 
    __m128i cmp = input;                                    //...X...X.X.XX...  (signs)
    UINT32 mask = _mm_movemask_epi8(cmp);                   //6792 - magic index
    __m128i shuf = shuffleTable[mask];                      //10 -1 -1 -1 8 -1 -1 -1 6 5 4 -1 2 1 0 -1 
    __m128i arr = _mm_shuffle_epi8(input, shuf);            //3 0 0 0 | 1 0 0 0 | 7 6 1 0 | 2 9 1 0 
    __m128i coeffs = _mm_set_epi8(0, 100, 10, 1, 0, 100, 10, 1, 0, 100, 10, 1, 0, 100, 10, 1);
    __m128i prod = _mm_maddubs_epi16(coeffs, arr);          //3 0 | 1 0 | 67 100 | 92 100 
    prod = _mm_hadd_epi16(prod, prod);                      //3 | 1 | 167 | 192 | ? | ? | ? | ?
    __m128i imm = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, 4, 2, 0);
    prod = _mm_shuffle_epi8(prod, imm);                     //3 1 167 192 0 0 0 0 0 0 0 0 0 0 0 0
    return _mm_extract_epi32(prod, 0);
//  return (UINT32(_mm_extract_epi16(prod, 1)) << 16) + UINT32(_mm_extract_epi16(prod, 0)); //no SSE 4.1
}

优点:

  • 比原始代码快 7.8 倍。
  • 每秒处理超过 3 亿个地址(单核,3.4 GHz)。
  • 利用矢量化指令实现最大吞吐量。

附加说明:

  • shuffleTable 需要预先计算。
  • @IwillnotexistIdonotexist 修改的代码将 shuffleTable 大小减少到 4Kb轻微的性能成本。

以上是有没有更快的方法将 IPv4 地址从字符串转换为整数?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn