Maison  >  Article  >  développement back-end  >  Existe-t-il un moyen plus rapide de convertir des adresses IPv4 de chaînes en entiers ?

Existe-t-il un moyen plus rapide de convertir des adresses IPv4 de chaînes en entiers ?

Patricia Arquette
Patricia Arquetteoriginal
2024-11-17 07:35:04531parcourir

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

Une alternative efficace pour convertir les adresses IPv4 à partir de chaînes

Q : Améliorer la vitesse d'analyse des adresses IPv4 à partir de chaînes

Les solutions existantes pour analyser les adresses IPv4 à partir de chaînes peuvent être lentes, limitant le débit. Existe-t-il une méthode plus rapide ou une alternative viable ?

A : Une solution vectorisée avec SSE4.1

Vue d'ensemble

Pour maximiser les performances d'analyse, une solution vectorisée exploitant les instructions SSE4.1 offre une vitesse significative avantages :

Code

__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
}

Avantages :

  • 7,8 fois plus rapide que le code d'origine.
  • Traite plus de 300 millions d'adresses par seconde (single core, 3.4 GHz).
  • Exploite les instructions vectorisées pour un débit maximal.

Remarques supplémentaires :

  • Le shuffleTable nécessite un précalcul.
  • Le code modifié par @IwillnotexistIdonotexist réduit la taille du shuffleTable à 4 Ko à un léger coût de performance.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn