Kod semasa anda untuk menghuraikan alamat IPv4 agak cekap, tetapi ia boleh dioptimumkan lagi untuk kelajuan yang lebih tinggi. Satu pendekatan ialah menggunakan penyelesaian vektor yang direka khusus untuk tugas ini.
Untuk pemproses x86 yang menyokong arahan SSE4.1 atau SSSE3, berikut ialah penyelesaian bervektor yang meningkatkan prestasi dengan ketara :
__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 }
Untuk menggunakan penyelesaian bervektor ini dengan berkesan, ia memerlukan jadual shuffle yang telah dikira sebelumnya, shuffleTable, yang boleh dijana seperti berikut:
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)); } } }
Pada pemproses Ivy Bridge, penyelesaian vektor menunjukkan prestasi yang mengagumkan, memproses 336 juta alamat sesaat. Ini adalah kira-kira 7.8 kali lebih pantas daripada kod yang diberikan dalam soalan asal.
Atas ialah kandungan terperinci Bagaimana untuk meningkatkan kelajuan penghuraian alamat IP menggunakan penyelesaian vektor?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!