
рд▓реЗрдЦ [рд▓рд┐рдВрдХ] рдиреЗ рдХрд╣рд╛ рдХрд┐ рд╣рд╛рд╕реНрдХреЗрд▓ рдХреЛрдб рдХрд╛ рдкреНрд░рджрд░реНрд╢рди C ++ рдХреЛрдб рд╕реЗ рдмреЗрд╣рддрд░ рдерд╛ред рдХреНрдпрд╛ рддреБрд░рдВрдд рд░реБрдЪрд┐ рдЬрдЧреА, рдЬреИрд╕рд╛ рдХрд┐ рджреЛрдиреЛрдВ рдХрдВрдкрд╛рдЗрд▓рд░ рджреНрд╡рд╛рд░рд╛ LLVM рджреНрд╡рд╛рд░рд╛ рдЙрддреНрдкрдиреНрди рдХрд┐рдП рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдпрд╛ рддреЛ рдПрд╕реНрд╕реЗрд▓ рдХрдВрдкрд╛рдЗрд▓рд░ рдХреЛ рдЕрдзрд┐рдХ рд╕рдВрдХреЗрдд рджреЗ рд╕рдХрддрд╛ рд╣реИ, рдпрд╛ C ++ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд╕рд╛рде рдХреБрдЫ рдЧрд▓рдд рд╣реИред рдЗрд╕рдХреЗ рдмрд╛рдж, рд╣рдо рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░реЗрдВрдЧреЗ рдХрд┐ рд▓реЗрдЦрдХ рдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ рджреБрд░реНрдШрдЯрдирд╛рдУрдВ рдХреА рдПрдХ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдиреЗ рдЧрд▓рдд рдирд┐рд╖реНрдХрд░реНрд╖ рдХреИрд╕реЗ рдирд┐рдХрд╛рд▓реЗ, рдЬреЛ рдиреАрдЪреЗ рджреА рдЧрдИ рддрд╛рд▓рд┐рдХрд╛ (рдХрдЯ рдХреЗ рддрд╣рдд) рдореЗрдВ рд╡рд░реНрдгрд┐рдд рд╣реИрдВред
рдкреНрд░рд╕реНрддрд╛рд╡рдирд╛
рд╣рд╛рд▓ рд╣реА рдореЗрдВ, рдПрдХ рдФрд░ рд▓реЗрдЦ рд╕реЗ0xd34df00dрд╣рд╛рд╕реНрдХреЗрд▓ рдХреЛрдб рдЕрдиреБрдХреВрд▓рдиред рдЗрд╕рдХреА рддреБрд▓рдирд╛ рдРрд╕реЗ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ рдкреНрд░рджрд░реНрд╢рди рдореЗрдВ рдирд┐рд░реНрд╡рд┐рд╡рд╛рдж рдиреЗрддрд╛ рдХреЗ рд╕рд╛рде рдХреА рдЬрд╛рддреА рд╣реИ - C / C ++ред рдлрд┐рд░ рдЗрд╕ рд▓реЗрдЦ рд╕реЗ рдПрдХ рдкрд░рд╕рд┐рдВрдЧ рдЖрдИyleoрдХреНрдпрд╛ asm рдХреЛрдб рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдмреЗрд╣рддрд░ рд╣реИ, рдФрд░ рд╡рд┐рднрд┐рдиреНрди рднрд╛рд╖рд╛рдУрдВ рдкрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рдмреАрдЪ рдЕрдВрддрд░ рдХреНрдпрд╛ рд╣реИ (рдореИрдВ рдкрдврд╝рдиреЗ рдХреА рд╕рд▓рд╛рд╣ рджреЗрддрд╛ рд╣реВрдВ)ред рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рднреА (рд▓рдЧрднрдЧ рдбреЗрдврд╝ рдорд╣реАрдиреЗ рдкрд╣рд▓реЗ), рд╣рд╛рд╕реНрдХреЗрд▓ рдмрдирд╛рдо рд╕реА / рд╕реА ++ рд╕реАрд░реАрдЬрд╝ рдХрд╛ рдкрд┐рдЫрд▓рд╛ рд▓реЗрдЦ рдкреНрд░рдХрд╛рд╢рд┐рдд рд╣реБрдЖ рдерд╛, рдФрд░ рдореИрдВрдиреЗ рднреА рдЗрд╕реА рддрд░рд╣ рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд┐рдпрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдЗрд╕реЗ рд╣рд╛рдмрд░рд╛ - рдЕрд▓рд╛рд╕ рдХреЛ рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп, рдореИрдВрдиреЗ рдЗрд╕реЗ рдмреИрдХ рдмреЙрдХреНрд╕ рдореЗрдВ рдбрд╛рд▓ рджрд┐рдпрд╛ред рдЗрд╕ рд╕рдкреНрддрд╛рд╣ рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдореЗрдВ рдЧрд░реНрдо рдЪрд░реНрдЪрд╛рдУрдВ рдиреЗ рдореБрдЭреЗ рдкрд┐рдЫрд▓реЗ рд╡рд┐рд╖рдп рдкрд░ рд▓реМрдЯрдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░реЗрд░рд┐рдд рдХрд┐рдпрд╛ред рдЖрдЬ рдореБрдЭреЗ рдЕрдВрдд рдореЗрдВ рджрд░рд╛рдЬ рдХреЗ рдмрд╛рд╣рд░ рдЙрд╕ рдорд╛рд░реНрдХрдбрд╛рдЙрди рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдорд┐рд▓рд╛, рдЬреЛ рдзреВрд▓ рд╕реЗ рд╕рдирд╛ рд╣реБрдЖ рдерд╛,рдЦрд╝рддреНрдо рд╣реЛрдирд╛, рдФрд░ рдЗрд╕реЗ рдЕрдкрдиреА рд╕рдореАрдХреНрд╖рд╛ рдХреЗ рд▓рд┐рдП рдкреНрд░рджрд╛рди рдХрд░реЗрдВред
рдкрд░рд┐рдЪрдп
, [], :
/++, .. , , " , ". "", . , , , 10- .
-, , ++ , , , . , zero-cost, , , , - ++, . , clang 3 (!) , +, , .. lang llvm тАФ .
, : gcc clang. , . ( ), gcc . , , , , , .
std::min({...})
, , std::min.
C++.
, std::min({delCost, insCost, substCost})
std::min(substCost, std::min(delCost, insCost))
,
clang тАФ 0.840
, .
( тАФ 0xd34df00d)
:
A.unsafeWrite v1 (j + 1) $ min (substCost + substCostBase) $ 1 + min delCost insCost
, min
! (, ). , , C++ , , llvm llvm. , . , , "skell " . , " ++; , PHP" , , . :
stdlib gcc - std::min
, ++. std::min_element
. , , , :
f(int, int, int):
cmp esi, edi
mov eax, edx
cmovg esi, edi
cmp esi, edx
cmovle eax, esi
ret
: cmov*
= conditional move (: g
тАФ greater, le
тАФ less equal, ..).
, , , , clang, gcc, - ( rsp ):
fptr(int*, int*, int*):
mov eax, dword ptr [rdi]
mov dword ptr [rsp - 12], eax
mov ecx, dword ptr [rsi]
mov dword ptr [rsp - 8], ecx
cmp ecx, eax
cmovle eax, ecx
mov ecx, dword ptr [rdx]
cmp ecx, eax
cmovle eax, ecx
ret
, clang . initializer_list
asm -O1
, (-O2
), asm . , std::min(std::initializer_list)
-, -, , .
s1[i]
, тАФ , ++.
s1[i]
! ()
, , , - , , . , s1[i]
,
let s1char = s1 `BS.index` i
let go j | j == n = pure ()
++, , clang. .. + llvm - , -march=native
. , , std::min
, , ! , - , " " , .
C++ .
,
C main', .
( )
, , , - , :
size_t lev_dist(const std::string &s1, const std::string &s2) {
const auto m = s1.size();
const auto n = s2.size();
std::vector<int> v0;
v0.resize(n + 1);
std::iota(v0.begin(), v0.end(), 0);
auto v1 = v0;
for (size_t i = 0; i < m; ++i) {
v1[0] = i + 1;
char c1 = s1[i];
for (size_t j = 0; j < n; ++j) {
auto substCost = c1 == s2[j] ? v0[j] : (v0[j] + 1);
v1[j + 1] = std::min(substCost, std::min(v0[j + 1], v1[j]) + 1);
}
std::swap(v0, v1);
}
return v0[n];
}
32- int
тАФ , ( ).
, GCC . j
, GCC. clang .
LLVM == LLVM
-, , ++ Haskell , clang-9. , Skylake C++ . , , , Haswell, .
, , , GCC LLVM.
, , llvm, ffi, .
GCC vs CLANG
-, , gcc . , clang- .
, , , , (#if !defined(__GNUC__) || defined(__llvm__)
), ++ , , ++ .
clang ( ) . ( )
, GCC LLVM. , asm. gcc - : , cmov* min ( , ). (3), , , ++ :
for (size_t j = 0; j < n; ++j) {
auto delCost = v0[j + 1] + 1;
auto insCost = v1[j] + 1;
auto substCost = c1 == s2[j] ? v0[j] : (v0[j] + 1);
v1[j + 1] = std::min(substCost, std::min(delCost, insCost));
}
, , :
.L42:
inc rcx // j++
mov rdi, QWORD PTR [r12+rcx*8] // v0[j+1]
xor edx, edx // %edx
cmp r10b, BYTE PTR [r11-1+rcx] // c1 == s2[j]
setne dl // %rdx
lea r9, [rdi+1] // v0[j+1] + 1
add rdx, QWORD PTR [r12-8+rcx*8] // v0[j]
lea rsi, [rax+1] // %rax v1[j]
cmp rdi, rax // v0[j+1] v1[j] += 1
mov rax, r9
cmovg rax, rsi // += 1
cmp rax, rdx // %rax, %rdx
cmovg rax, rdx
mov QWORD PTR [r8+rcx*8], rax // v1[j+1] = ...
cmp rbx, rcx // loop
jne .L42
, тАФ v1[j]
%rax
.
LLVM, - , . , , :
.LBB1_40: # in Loop: Header=BB1_36 Depth=2
mov qword ptr [r14 + 8*rsi + 8], rax
mov rdx, qword ptr [rbx + 8*rsi + 16]
inc rdx
inc rax
xor ebp, ebp
cmp cl, byte ptr [r13 + rsi + 1]
setne bpl
add rbp, qword ptr [rbx + 8*rsi + 8]
cmp rax, rdx
jg .LBB1_41
lea rdi, [rsi + 2]
cmp rax, rbp
jle .LBB1_44
jmp .LBB1_43
: jmp, j*
= jump (: jg
тАФ greater, jle
тАФ less equal, ..).
v0[j+1]
, v0[j]
, cmp
s1[i]
, cmp + jump . , , ( , ) , , . тАФ .
, GCC , LLVM 2 (!) , .
, . : (jump), тАФ (cmov).
, тАФ .
, , . , , PGO (, JIT ). , GCC PGO clang. тАФ , . , , // , , , .
- , тАФ
- , LLVM
- , GCC LLVM ,
- ffi. , .. , , ,
, , .
: , , "" , , . Rust (, ).
P.S.
тАФ , -
( )
, тАФ , .. , , , s1 s2. . -, O(n*m) ( for). , . , k. , . , .
LinearLeopard .
- :
-O3 -march=native -std=gnu++17
. - рдкреНрд░реЛрд╕реЗрд╕рд░: рдЗрдВрдЯреЗрд▓ i5-8250U (рд╣рд╛рдБ, рд▓реИрдкрдЯреЙрдк)
- OS: рдЙрдмрдВрдЯреВ 19.04 / рд▓рд┐рдирдХреНрд╕ 5.0.0
- рдЯрд░реНрдмреЛ рдмреВрд╕реНрдЯ рдореЗрдВ рддреЗрдЬреА рд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд╣рд▓рд╛ рд░рди, рдлрд┐рд░ рдПрдХ рдкрдВрдХреНрддрд┐ рдореЗрдВ рдиреНрдпреВрдирддрдо рдкрд╛рдВрдЪред 1-2% рдХреЗ рднреАрддрд░ рд╡рд┐рдЪрд▓рдиред
- рд╡рд┐рднрд┐рдиреНрди 1s рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд▓реЙрдиреНрдЪ рдХреЗ рдмреАрдЪ, рд╣рдо рд╢рд╛рдВрдд рд╣реЛ рдЬрд╛рдПрдВрдЧреЗ (рд╣рд╛рдБ, рд▓реИрдкрдЯреЙрдк)
рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛: рдЖрд▓рд╕реА рдХреЗ рд▓рд┐рдП рд╕реНрдХреНрд░рд┐рдкреНрдЯ
рдЖрдк рдЕрдкрдиреЗ рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рдкрд░ рдПрдХ рд╣реА рдЪреАрдЬрд╝ рдЪрд▓рд╛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЬрдирддрд╛ рдХреЛ рдЗрд╕рдХрд╛ рдкрд░рд┐рдгрд╛рдо рдмрддрд╛ рд╕рдХрддреЗ рд╣реИрдВ: рдЧреАрдердм рдХрд╛ рд▓рд┐рдВрдХ ред
рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛: -march = рджреЗрд╢реА рдХреЗ рдмрд┐рдирд╛ рдкрд░рд┐рдгрд╛рдо
рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдореЗрдВ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рдЕрдиреБрд╕рд╛рд░, рдореИрдВрдиреЗ рдЗрд╕ рдзреНрд╡рдЬ рдХреЗ рдкреНрд░рднрд╛рд╡ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ред