рд╕рдмрд╕реЗ рддреЗрдЬ рд╕реНрдЯреНрд░рд▓реЗрди рдХреИрд╕реЗ рди рдмрдирд╛рдПрдВ рдФрд░ рд╡рд┐рдЬреБрдЕрд▓ рд╕реНрдЯреВрдбрд┐рдпреЛ 2019 рдХрдореНрдпреБрдирд┐рдЯреА рдореЗрдВ рдПрдХ рджреЛрд╖ рдЦреЛрдЬреЗрдВ

рдореБрдЭреЗ рдЖрдзреБрдирд┐рдХ рдкреНрд░реЛрд╕реЗрд╕рд░ рдореЗрдВ "рдЕрдЬреАрдм" рдкреЙрдкрдХреЙрдЗрди рдЕрдиреБрджреЗрд╢ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рд▓реЗрдЦ рджреНрд╡рд╛рд░рд╛ рдкреНрд░реЗрд░рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдпрд╣ рдЗрдХрд╛рдЗрдпреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреА рдЧрд┐рдирддреА рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдирд╣реАрдВ рд╣реИ, рдмрд▓реНрдХрд┐ рдПрдХ рд╕реА рд▓рд╛рдЗрди рдХреЗ рдЕрдВрдд рдХреЗ рд╕рдВрдХреЗрдд рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╣реИ (рдПрдХ рд╢реВрдиреНрдп-рд╕рдорд╛рдкреНрдд рд▓рд╛рдЗрди )ред
рдПрдХ рдирд▓-рд╕рдорд╛рдкреНрдд рд╕реНрдЯреНрд░рд┐рдВрдЧ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛рдУрдВ рдореЗрдВ рддрд╛рд░ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдПрдХ рд╡рд┐рд╢реЗрд╖ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдкреНрд░рдХрд╛рд░ рдХреЛ рдкреЗрд╢ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп, рд╡рд░реНрдгреЛрдВ рдХреА рдПрдХ рд╕рд░рдгреА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рдЕрдВрдд рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝рд╛ рдкрд╣рд▓рд╛ рд╡рд┐рд╢реЗрд╖ рд╢реВрдиреНрдп рдЪрд░рд┐рддреНрд░ рд╣реИ (ASC рдХреЛрдб рд╕реЗ NUL, 0 рдХреЗ рдорд╛рди рдХреЗ рд╕рд╛рде)ред

рдЗрд╕ рддрд░рд╣ рдХреА рдЕрд╡рдзрд┐ рдХреА рд▓рдВрдмрд╛рдИ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ рдорд╛рдирдХ рдлрд╝рдВрдХреНрд╢рди рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

size_t __cdecl strlen(char const* str) 

рдСрдкрд░реЗрд╢рди рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдЬрд┐рд╕рдореЗрдВ рд╕реА рдХреЗ рд░реВрдк рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:

 size_t strlen_algo(const char* str) { size_t length = 0; while (*str++) length++; return length; } 

рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рдПрдордПрд╕ рд╡рд┐рдЬрд╝реБрдЕрд▓ рд╕реНрдЯреВрдбрд┐рдпреЛ 2019 рдХрдореНрдпреБрдирд┐рдЯреА рдХрдВрдкрд╛рдЗрд▓рд░ (рд░рд┐рд▓реАрдЬрд╝, x86) рдЗрд╕реЗ рдХреНрдпрд╛ рдореЛрдбрд╝ рджреЗрддрд╛ рд╣реИ:

 08811F7h: mov al,byte ptr [ecx] inc ecx test al,al jne main+0D7h (08811F7h) 

рдпрд╣реА рд╣реИ, рдПрдХ рдмрд╛рдЗрдЯ рдХреЛ рдореЗрдореЛрд░реА рд╕реЗ рд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рд╢реВрдиреНрдп рдХреЗ рд╕рд╛рде рддреБрд▓рдирд╛ рдХреА рдЬрд╛рддреА рд╣реИред рдпрджрд┐ рдЖрдк рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЛ рд░рд┐рд▓реАрдЬрд╝ рдореЗрдВ рдмрдирд╛рддреЗ рд╣реИрдВ, рддреЛ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рд╕рд╣реА рд╣реИ, рдЙрд╕реА рдХреЛрдб рдХреЛ рд╕реНрдЯреНрд░реИрд▓реЗрди рдХреЙрд▓реНрд╕ рдХреЗ рд▓рд┐рдП рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЧрддрд┐, рдпрд╣ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ, рдкрд░реНрдпрд╛рдкреНрдд рдирд╣реАрдВ рд╣реИред рдпрджрд┐ рдЖрдк рдХреЛрдб рдХреЛ рдбрд┐рдмрдЧ рдореЗрдВ рдПрдХ рдорд╛рдирдХ strlen рдХреЗ рд╕рд╛рде рдХреЛрдб рд╕рдВрдХрд▓рд┐рдд рдХрд░рддреЗ рд╣реИрдВ рддреЛ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИ? - рд╕реНрдЯреНрд░рд▓реЗрди рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдЙрдореНрдореАрдж рдХреЗ рдореБрддрд╛рдмрд┐рдХ рдХрд╣рд╛ рдЬрд╛рдПрдЧрд╛, рд▓реЗрдХрд┐рди рдХреЛрдбрд╛рдВрддрд░рдХ рдкрд░ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдПрдХ рд╡реНрдпрдХреНрддрд┐ рджреНрд╡рд╛рд░рд╛ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИред

MS Visual Studio рдореЗрдВ рдорд╛рдирдХ рд╕реНрдЯреНрд░реИрд▓реЗрди рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдХреЛрдб рдмрд┐рдЧрд╛рдбрд╝рдиреЗ рд╡рд╛рд▓рд╛
 ;strlen.asm - contains strlen() routine ; ; Copyright (c) Microsoft Corporation. All rights reserved. ; ;Purpose: ; strlen returns the length of a null-terminated string, ; not including the null byte itself. ; ;******************************************************************************* .xlist include cruntime.inc .list page ;*** ;strlen - return the length of a null-terminated string ; ;Purpose: ; Finds the length in bytes of the given string, not including ; the final null character. ; ; Algorithm: ; int strlen (const char * str) ; { ; int length = 0; ; ; while( *str++ ) ; ++length; ; ; return( length ); ; } ; ;Entry: ; const char * str - string whose length is to be computed ; ;Exit: ; EAX = length of the string "str", exclusive of the final null byte ; ;Uses: ; EAX, ECX, EDX ; ;Exceptions: ; ;******************************************************************************* CODESEG public strlen strlen proc \ buf:ptr byte OPTION PROLOGUE:NONE, EPILOGUE:NONE .FPO ( 0, 1, 0, 0, 0, 0 ) string equ [esp + 4] mov ecx,string ; ecx -> string test ecx,3 ; test if string is aligned on 32 bits je short main_loop str_misaligned: ; simple byte loop until string is aligned mov al,byte ptr [ecx] add ecx,1 test al,al je short byte_3 test ecx,3 jne short str_misaligned add eax,dword ptr 0 ; 5 byte nop to align label below align 16 ; should be redundant main_loop: mov eax,dword ptr [ecx] ; read 4 bytes mov edx,7efefeffh add edx,eax xor eax,-1 xor eax,edx add ecx,4 test eax,81010100h je short main_loop ; found zero byte in the loop mov eax,[ecx - 4] test al,al ; is it byte 0 je short byte_0 test ah,ah ; is it byte 1 je short byte_1 test eax,00ff0000h ; is it byte 2 je short byte_2 test eax,0ff000000h ; is it byte 3 je short byte_3 jmp short main_loop ; taken if bits 24-30 are clear and bit ; 31 is set byte_3: lea eax,[ecx - 1] mov ecx,string sub eax,ecx ret byte_2: lea eax,[ecx - 2] mov ecx,string sub eax,ecx ret byte_1: lea eax,[ecx - 3] mov ecx,string sub eax,ecx ret byte_0: lea eax,[ecx - 4] mov ecx,string sub eax,ecx ret strlen endp end 


рддрд╛рд▓рд┐рдХрд╛ 1 - рд╕реЗрдХрдВрдб рдореЗрдВ рд╕реНрдЯреНрд░реЗрд▓рди рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдХрд╛ рд░рдирдЯрд╛рдЗрдо (рдПрдордПрд╕ рд╡реАрдПрд╕ 2019 рд╕рдореБрджрд╛рдп, рд╕реА ++ рд╕реАрдПрд▓ рд╕рдВрд╕реНрдХрд░рдг: 19.22.27909)

рдмрдбрд╝рд╛ рдмреНрд▓реЙрдХ, 1Kрдмрд┐рдЧ рдмреНрд▓реЙрдХ, 1K, * рд╕реНрдЯреНрд░рд▓реЗрди рдХреЙрд▓рдЫреЛрдЯрд╛ рдмреНрд▓реЙрдХ, 10 рддрддреНрд╡рдЫреЛрдЯреЗ рдмреНрд▓реЙрдХ, 10 рддрддреНрд╡, * рд╕реНрдЯреНрд░рд▓реЗрди рдХреЙрд▓
рдбрд┐рдмрдЧ, x867.257.253.063.06
рд░рд┐рд▓реАрдЬрд╝, x869.03.90.150.12
рдбрд┐рдмрдЧ, x646.06.03.43.4
рд░рд┐рд▓реАрдЬрд╝, x648.52.30.150.11

* рдХрдВрдкрд╛рдЗрд▓рд░ рдХреЛ рд╕реНрдЯреНрд░реИрдирд▓ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╛рдзреНрдп рдХрд░реЗрдВ

рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╣рдо рдпрд╣ рдирд┐рд╖реНрдХрд░реНрд╖ рдирд┐рдХрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдПрдордПрд╕ рд╡реА.рдПрд╕. рдХрдореНрдкрд╛рдЗрд▓рд░ рджреНрд╡рд╛рд░рд╛ рдмрд╛рдЗрдЯ рддреБрд▓рдирд╛ рдХрд╛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдЫреЛрдЯреЗ рддрд╛рд░реЛрдВ рдкрд░ рднреА рдЕрдХреНрд╖рдо рд╣реИ, рдФрд░ рдмрдбрд╝реЗ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдкрд░, рдбрд┐рдмрдЧ рд░рд┐рд▓реАрдЬ рд╕реЗ рдЖрдЧреЗ рд╣реИ!

рдмреЗрдВрдЪ рдХреЛрдб
 #include <iostream> #include <string> #include <vector> #include <chrono> #include <nmmintrin.h> inline size_t strlen_algo(const char* str) { size_t length = 0; while (*str++) length++; return length; } inline size_t strlen_sse4(const char* str) { size_t length = 0; int res = 0; //align to 16 bytes while (((size_t(str+length)) & (sizeof(__m128i) - 1)) != 0) { if (str[length] == 0) return length; length++; } __m128i z128 = _mm_setzero_si128(); for(; ; length += 16) { __m128i data = _mm_load_si128((__m128i*)(str + length)); if ((res = _mm_cmpistri(z128, data, _SIDD_CMP_EQUAL_EACH)) != 16) break; } /*while (str[length]) length++;*/ return length + res; } #define _DISABLE_ASM_BSF //https://www.strchr.com/sse2_optimised_strlen #ifndef WORDS_BIGENDIAN #if 0 #elif 0 #else static inline int count_bits_to_0(unsigned int x) // counting trailing zeroes, by Nazo, post: 2009/07/20 03:40 { // this is current winner for speed static const unsigned char table[256] = { 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, }; if ((unsigned char)x) return table[(unsigned char)x]; return table[x >> 8] + 8; // t[x / 256] + 8 } #endif #else #if 0 static inline int count_bits_to_0(unsigned int x) // counting trailing zeroes { register int i = 0; if (!(x & (1 << 15))) i++; else return i; if (!(x & (1 << 14))) i++; else return i; if (!(x & (1 << 13))) i++; else return i; if (!(x & (1 << 12))) i++; else return i; if (!(x & (1 << 11))) i++; else return i; if (!(x & (1 << 10))) i++; else return i; if (!(x & (1 << 9))) i++; else return i; if (!(x & (1 << 8))) i++; else return i; if (!(x & (1 << 7))) i++; else return i; if (!(x & (1 << 6))) i++; else return i; if (!(x & (1 << 5))) i++; else return i; if (!(x & (1 << 4))) i++; else return i; if (!(x & (1 << 3))) i++; else return i; if (!(x & (1 << 2))) i++; else return i; if (!(x & (1 << 1))) i++; else return i; if (!(x & (1 << 0))) i++; return i; } #else static inline int count_bits_to_0(unsigned int x) // counting trailing zeroes { // http://www.hackersdelight.org/: nlz1() shortened for 16-bit mask register int n = 0; if (x <= 0x000000FFU) { n = n + 8; x = x << 8; } if (x <= 0x00000FFFU) { n = n + 4; x = x << 4; } if (x <= 0x00003FFFU) { n = n + 2; x = x << 2; } if (x <= 0x00007FFFU) { n = n + 1; } return n; } #endif #endif size_t strlen2(const char* str) { register size_t len = 0; // align to 16 bytes while ((((intptr_t)str) & (sizeof(__m128i) - 1)) != 0) { if (*str++ == 0) return len; ++len; } // search for 0 __m128i xmm0 = _mm_setzero_si128(); __m128i xmm1; int mask = 0; for (;;) { xmm1 = _mm_load_si128((__m128i*)str); xmm1 = _mm_cmpeq_epi8(xmm1, xmm0); if ((mask = _mm_movemask_epi8(xmm1)) != 0) { // got 0 somewhere within 16 bytes in xmm1, or within 16 bits in mask // find index of first set bit #ifndef _DISABLE_ASM_BSF // define it to disable ASM #if (_MSC_VER >= 1300) // make sure <intrin.h> is included unsigned long pos; _BitScanForward(&pos, mask); len += (size_t)pos; #elif defined(_MSC_VER) // earlier MSVC's do not have _BitScanForward, use inline asm __asm bsf edx, mask; edx = bsf(mask) __asm add edx, len; edx += len __asm mov len, edx; len = edx #elif ((__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))) // modern GCC has built-in __builtin_ctz len += __builtin_ctz(mask); #elif defined(__GNUC__) // older GCC shall use inline asm unsigned int pos; asm("bsf %1, %0" : "=r" (pos) : "rm" (mask)); len += (size_t)pos; #else // none of choices exist, use local BSF implementation len += count_bits_to_0(mask); #endif #else len += count_bits_to_0(mask); #endif break; } str += sizeof(__m128i); len += sizeof(__m128i); } return len; } int main() { std::vector<std::string> vstr; const int str_num = 1024; const int str_size = 1024; size_t len_result = 0; srand(0); for (int i = 0; i < str_num; i++) { std::string str1; for (int j = 0; j < str_size; j++) { str1.push_back('0' + rand() % 78); } vstr.push_back(std::move(str1)); } auto strlen_func = strlen; //auto strlen_func = strlen_algo; //auto strlen_func = strlen_sse4; //auto strlen_func = strlen2; auto time_std = std::chrono::steady_clock::now(); for (int k = 0; k < 10*1000; k++) { for (int i = 0; i < str_num; i++) { const char* str_for_test = vstr[i].c_str(); len_result += strlen_func(str_for_test); //len_result += strlen(str_for_test); } for (int i = 0; i < str_num; i++) { const char* str_for_test = vstr[i].c_str(); len_result -= strlen_func(str_for_test); //len_result -= strlen(str_for_test); } } auto finish = std::chrono::steady_clock::now(); double elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double>>(finish - time_std).count(); std::cout << "\n" << len_result; std::cout << "\n\nTime: " << elapsed_seconds; return 0; } 


рдкрдВрдХреНрддрд┐
 len_result += strlen(str_for_test); 
рд╕рдВрдХрд▓рд┐рдд
рдбрд┐рдмрдЧ рдЗрди: рд╕реНрдЯреНрд░рд▓реЗрди рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛;
рдореЗрдВ рд░рд┐рд▓реАрдЬ: рдмрд╛рдЗрдЯ рддреБрд▓рдирд╛ред

рдЕрдЧрд░ рдЖрдк рдХрдореЗрдВрдЯ рдХрд░рдХреЗ рдЬрд░реБрд░ рд▓рд┐рдЦреЗ

 len_result += strlen_func(str_for_test); 

рдЬрд╣рд╛рдБ

 auto strlen_func = strlen; 

рд╣рдо рд╕рдВрдХрд▓рдХ рдХреЛ рд╣рдореЗрд╢рд╛ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдордЬрдмреВрд░ рдХрд░реЗрдВрдЧреЗред

рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдлрд╝рдВрдХреНрд╢рди рдХреЗ рддреНрд╡рд░рдг рдХреЛ рдмрд╛рдЗрдЯ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ 2.3 рдЧреБрдирд╛ (рд░рд┐рд▓реАрдЬ, x86, 1k рдХреЗ рд▓рд┐рдП) рд╕реЗ рдкрд╣рд▓реЗ рд╣рд╛рд╕рд┐рд▓ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛?

рддреБрд▓рдирд╛ рдХреЗ рдХрд╛рд░рдг рдПрдХ рдмрд╛рдЗрдЯ рд╕реЗ рдирд╣реАрдВ, рдмрд▓реНрдХрд┐ рддреБрд░рдВрдд 4 рд╕реЗред рдпрд╣рд╛рдВ рд╕рднреА рдЬрд╛рджреВ:

 main_loop: mov eax,dword ptr [ecx] ; read 4 bytes mov edx,7efefeffh add edx,eax xor eax,-1 xor eax,edx add ecx,4 test eax,81010100h je short main_loop 

рдХреНрдпрд╛ рдЖрдзреБрдирд┐рдХ рдкреНрд░реЛрд╕реЗрд╕рд░ рдХреЗ рд╡реЗрдХреНрдЯрд░ рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рддреЗрдЬреА рд╕реЗ рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИ? рдЪрд▓реЛ рдЗрд╕реЗ рдЖрдЬрдорд╛рдПрдБред

Intel Intrinsics рдЧрд╛рдЗрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рд╣рдо рдЖрдВрддрд░рд┐рдХ _mm_cmpistri SSE4.2 рдкрд╛рддреЗ рд╣реИрдВ, рдЬрд┐рд╕реЗ рдХреЗрд╡рд▓ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред 128 рдмрд┐рдЯ рдХреА рд▓рдВрдмрд╛рдИ рд╡рд╛рд▓реЗ рджреЛ рд╡реИрдХреНрдЯрд░ рдФрд░ рдСрдкрд░реЗрд╢рди рдХрд╛ рдПрдХ рдореБрдЦреМрдЯрд╛ рдЗрдирдкреБрдЯ рдХреЛ рдЦрд┐рд▓рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдорд╛рд╕реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ рд╣рдо рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ: _SIDD_UBYTE_OPS = 0 - рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░, _SIDD_CMP_EQUAL_EACH = 8 - рдмрд╛рдЗрдЯ рд╕рдВрд░реЗрдЦрдг рдХрд╛ рд╕рдВрдЪрд╛рд▓рди, рдФрд░ рд╣рдо рдПрдХ рд╢реВрдиреНрдп рд╡реЗрдХреНрдЯрд░ рдХреЗ рд╕рд╛рде рддреБрд▓рдирд╛ рдХрд░реЗрдВрдЧреЗред рд▓реМрдЯрд╛рдпрд╛ рдЧрдпрд╛ рдореВрд▓реНрдп рдкрд╣рд▓реЗ рдЬреЛрдбрд╝реАрджрд╛рд░ рдЕрд╕рдорд╛рди рддрддреНрд╡реЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рд╣реЛрдЧреА (рдпрд╛рдиреА, рдЕрдЧрд░ рддрддреНрд╡ рдмрд╛рдПрдВ рд╕реЗ рджрд╛рдПрдВ рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИ, рддреЛ рдЧрд┐рдирддреА рдмрдВрдж рд╣реЛ рдЬрд╛рддреА рд╣реИ, рдореБрдЭреЗ рдЦреБрд╢реА рд╣реЛрдЧреА рдЕрдЧрд░ рдХреЛрдИ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреА рдкреБрд╖реНрдЯрд┐ рдХрд░рддрд╛ рд╣реИ)ред

 size_t length = 0; int res = 0; //align to 16 bytes while (((size_t(str+length)) & (sizeof(__m128i) - 1)) != 0) { if (str[length] == 0) return length; length++; } __m128i z128 = _mm_setzero_si128(); for(; ; length += 16) { __m128i data = _mm_load_si128((__m128i*)(str + length)); if ((res = _mm_cmpistri(z128, data, _SIDD_CMP_EQUAL_EACH)) != 16) break; } /*while (str[length]) length++;*/ return length + res; 

рдХреЛрдб

 while (((size_t(str+length)) & (sizeof(__m128i) - 1)) != 0) { if (str[length] == 0) return length; length++; } 

рд▓реЛрдб рдХрд┐рдП рдЧрдП рд▓рд╛рдЗрди рдХреЗ рдкрддреЗ рдХреЛ рдмрд░рд╛рдмрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИ, рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХрд╛рдВрд╢ рдПрд╕рдПрд╕рдИ рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЗ рд▓рд┐рдП рдкрддреЗ рдХреЛ 16 рдХреЗ рдЧреБрдгрдХреЛрдВ рдореЗрдВ рдЖрд╡рд╢реНрдпрдХ рд╣реИред рд╣рдорд╛рд░реЗ рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдкреАрд╕реАрдкрд┐рд╕реНрдЯрд░реА рдирд┐рд░реНрджреЗрд╢ рдХреЗ рд▓рд┐рдП, рд╕рдВрд░реЗрдЦрдг рдХрдбрд╝рд╛рдИ рд╕реЗ рдЖрд╡рд╢реНрдпрдХ рдирд╣реАрдВ рд╣реИ, рдПрдХ рдПрдХреНрд╕реЗрд╕ рдЕрдкрд╡рд╛рдж рдирд╣реАрдВ рдлреЗрдВрдХрд╛ рдЬрд╛рдПрдЧрд╛ред
Intrinsiki
 __m128i data = _mm_load_si128((__m128i*)(str + length)); if ((res = _mm_cmpistri(z128, data, _SIDD_CMP_EQUAL_EACH)) != 16) 

рдЗрд╕рдореЗрдВ рд╕рдВрдХрд▓рд┐рдд:
 pcmpistri xmm1,xmmword ptr [eax+edx],8 

рд╣рд╛рд▓рд╛рдВрдХрд┐, 16 рд╕реЗ рд╕рдВрд░реЗрдЦрд┐рдд рдХрд░рдирд╛ рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рднреА рдЙрдкрдпреЛрдЧреА рд╣реИ, рдпрд╣ рдЧрддрд┐ рдореЗрдВ рдПрдХ рдЫреЛрдЯреА рд╡реГрджреНрдзрд┐ рджреЗрддрд╛ рд╣реИ, рдФрд░ рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ рдпрдХреАрди рд╣реИ рдХрд┐ 16 рдмрд╛рдЗрдЯреНрд╕ рдХрд╛ рдПрдХ рдкрдврд╝рд╛ рд╣реБрдЖ рдЪрдХреНрд░ рд╕рдВрднрд╛рд╡рд┐рдд рдЕрд╕рдВрдмрджреНрдз рдкреГрд╖реНрда ( 4K рдореЗрдореЛрд░реА рдкреЗрдЬ ) рдкрд░ рдирд╣реАрдВ рдЬрд╛рдПрдЧрд╛ред

рдЪрдХреНрд░:
 while (str[length]) length++; 

рдпрджрд┐ рдЗрд╕рдХреЗ рдЕрдВрдд рдХрд╛ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ, рддреЛ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХрд╛ рдЖрдХрд╛рд░ "рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ" (рдХреНрдпреЛрдВрдХрд┐ рдореИрдВ рдСрдкрд░реЗрд╢рди рдХреЗ _mm_cmpistri рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкреВрд░реА рддрд░рд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдирд╣реАрдВ рд╣реВрдВ)ред
рдЪреБрдЯреАрд▓реА рдЯрд┐рдкреНрдкрдгреА рдХреЗ рдмрд╛рдж рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЧрдпрд╛, рдЬрд┐рд╕рд╕реЗ рдЫреЛрдЯреА рд▓рд╛рдЗрдиреЛрдВ рдкрд░ рд╡реГрджреНрдзрд┐ рд╣реБрдИред

рдХреНрдпрд╛ рд╣рдордиреЗ рд╕рдмрд╕реЗ рддреЗрдЬ рд╕реНрдЯреНрд░реИрд▓реЗрди рдмрдирд╛рдпрд╛? - рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рдирд╣реАрдВ, рджреЛрд╕реНрддреЛрдВ, https://www.strchr.com/sse2_optimised_strlen рдиреЗ рднреА рддреЗрдЬреА рд╕реЗ рдФрд░ SSE4.2 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдмрд┐рдирд╛ рдХрд┐рдпрд╛ред

рддрд╛рд▓рд┐рдХрд╛ 2 - рд╕реЗрдХрдВрдб рдореЗрдВ рд╕реНрдЯреНрд░рд▓реЗрди рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдХрд╛ рд░рдирдЯрд╛рдЗрдо (рд░рд┐рд▓реАрдЬрд╝)
рд╡рд░реНрдгреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛рдПрдордПрд╕ рдмрд╛рдЗрдЯ рддреБрд▓рдирд╛рд╕реБрд╢реНрд░реА рд╕реНрдЯреНрд░рд▓реЗрдирдПрд╕рдПрд╕рдИ 4.2рдПрд╕рдПрд╕рдИ реи
10, x860.150.120.120.125
1K, x869.03.91.651.42
10, x640.150.110.080.1
1K, x648.52.31.61.32

рдирд┐рд╖реНрдХрд░реНрд╖:

рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдкреНрд░рддреАрдд рд╣реЛрддрд╛ рд╣реИ рдХрд┐ рдПрдордПрд╕ рдХреЛ рд╣рдореЗрд╢рд╛ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╕реНрдЯреНрд░реИрд▓реЗрди рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдФрд░ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдмрд╛рдЗрдЯ рддреБрд▓рдирд╛ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред

рдпреБрдкреАрдбреАред
рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ x64 рдкрд░реАрдХреНрд╖рдгред
рдкрд┐рдЫрд▓реЗ рд▓реВрдк рдХреЛ strlen_SSE4 рдореЗрдВ рдирд┐рдХрд╛рд▓рд╛ рдЧрдпрд╛

Source: https://habr.com/ru/post/hi467699/


All Articles