IPv4 アドレスを解析するための現在のコードはかなり効率的ですが、さらに高速化するためにさらに最適化することができます。 1 つのアプローチは、このタスク専用に設計されたベクトル化ソリューションを利用することです。
SSE4.1 または SSSE3 命令をサポートする x86 プロセッサの場合、パフォーマンスを大幅に向上させるベクトル化ソリューションを次に示します。 :
__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 }
このベクトル化されたソリューションを効果的に利用するには、次のように生成できる事前計算されたシャッフル テーブル shuffleTable が必要です。
void MyInit() { memset(shuffleTable, -1, sizeof(shuffleTable)); int len[4]; for (len[0] = 1; len[0] <= 3; len[0]++) for (len[1] = 1; len[1] <= 3; len[1]++) for (len[2] = 1; len[2] <= 3; len[2]++) for (len[3] = 1; len[3] <= 3; len[3]++) { int slen = len[0] + len[1] + len[2] + len[3] + 4; int rem = 16 - slen; for (int rmask = 0; rmask < 1<<rem; rmask++) { // { int rmask = (1<<rem)-1; //note: only maximal rmask is possible if strings are zero-padded int mask = 0; char shuf[16] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; int pos = 0; for (int i = 0; i < 4; i++) { for (int j = 0; j < len[i]; j++) { shuf[(3-i) * 4 + (len[i]-1-j)] = pos; pos++; } mask ^= (1<<pos); pos++; } mask ^= (rmask<<slen); _mm_store_si128(&shuffleTable[mask], _mm_loadu_si128((__m128i*)shuf)); } } }
Ivy Bridge プロセッサーでは、ベクトル化されたソリューションは、1 秒あたり 3 億 3,600 万のアドレスを処理するという優れたパフォーマンスを示します。これは、元の質問で提供されたコードよりも約 7.8 倍高速です。
以上がベクトル化されたソリューションを使用して IP アドレスの解析速度を向上させるにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。