рдмрд┐рд▓реНрдЯ-рдЗрди рдЧреЛ рдлреАрдЪрд░


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

рдХреЛрдбрд╛рдВрддрд░рдХ рдореЗрдВ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд▓рд┐рдЦрдирд╛ рд╢реБрд░реВ рдХрд░рдирд╛ рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдлрд╝рдВрдХреНрд╢рди рдХреЛ Add (рдЖрдЧреЗ рдХреА рдШреЛрд╖рдгрд╛) рдШреЛрд╖рд┐рдд рдХрд░реЗрдВ, рдЬрд┐рд╕рдореЗрдВ 2 рдЗрдВрдЯ 64 рд╢рд╛рдорд┐рд▓ рд╣реИрдВ:

 func Add(a int64, b int64) int64 

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

 % go build examples/asm ./decl.go:4:6: missing function body 

рдПрдХреНрд╕рдЯреЗрдВрд╢рди .s рдХреЗ рд╕рд╛рде рдПрдХ рдлрд╝рд╛рдЗрд▓ рдЬреЛрдбрд╝реЗрдВ рдФрд░ рдХреЛрдбрд╛рдВрддрд░рдХ рдореЗрдВ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд▓рд╛рдЧреВ рдХрд░реЗрдВред

 TEXT ┬╖Add(SB),$0-24 MOVQ a+0(FP), AX ADDQ b+8(FP), AX MOVQ AX, ret+16(FP) RET 

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

рд▓реЗрдХрд┐рди рдПрдХ рд╕рдорд╕реНрдпрд╛ рд╣реИ - asm рдкрд░ рдлрдВрдХреНрд╢рдиреНрд╕ рдХреЛ рдСрдкреНрдЯрд┐рдорд╛рдЗрдЬрд╝ рдФрд░ рдмрд┐рд▓реНрдЯ-рдЗрди (рдЗрдирд▓рд╛рдЗрди) рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдмрд┐рдирд╛, рдУрд╡рд░рд╣реЗрдб рдирд┐рд╖реЗрдзрд╛рддреНрдордХ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред

 var Result int64 func BenchmarkAddNative(b *testing.B) { var r int64 for i := 0; i < bN; i++ { r = int64(i) + int64(i) } Result = r } func BenchmarkAddAsm(b *testing.B) { var r int64 for i := 0; i < bN; i++ { r = Add(int64(i), int64(i)) } Result = r } 

 BenchmarkAddNative-8 1000000000 0.300 ns/op BenchmarkAddAsm-8 606165915 1.930 ns/op 

рдЗрдирд▓рд╛рдЗрди рдЕрд╕реЗрдВрдмрд▓рд░ рдХреЗ рд▓рд┐рдП рдХрдИ рд╕реБрдЭрд╛рд╡ рджрд┐рдП рдЧрдП рдереЗ, рдХреНрдпреЛрдВрдХрд┐ gcc рдореЗрдВ asm(...) рдирд┐рд░реНрджреЗрд╢ред рдЙрдирдореЗрдВ рд╕реЗ рдХреЛрдИ рднреА рд╕реНрд╡реАрдХрд╛рд░ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдЗрд╕рдХреЗ рд╕реНрдерд╛рди рдкрд░, рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рдЖрдВрддрд░рд┐рдХ рдХрд╛рд░реНрдп рдХрд░рддреЗ рд╣реИрдВред

рдмрд┐рд▓реНрдЯ-рдЗрди рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд╕рд╛рджреЗ рдЧреЛ рдореЗрдВ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдХрдВрдкрд╛рдЗрд▓рд░ рдЬрд╛рдирддрд╛ рд╣реИ рдХрд┐ рдЙрдиреНрд╣реЗрдВ рдХреБрдЫ рдЕрдзрд┐рдХ рдЗрд╖реНрдЯрддрдо рдХреЗ рд╕рд╛рде рдмрджрд▓рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред 1.13 рдЧреЛ рдореЗрдВ, рдПрдореНрдмреЗрдбреЗрдб рдлрд╝рдВрдХреНрд╢рди math/bits рдФрд░ sync/atomic рдореЗрдВ рдирд┐рд╣рд┐рдд рд╣реИрдВред

рдЗрди рдкреИрдХреЗрдЬреЛрдВ рдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ рдлреИрдВрд╕реА рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рд╣реИрдВред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╡реЗ рдкреНрд░реЛрд╕реЗрд╕рд░ рдХрдорд╛рдВрдб рдХреЗ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рджреЛрд╣рд░рд╛рддреЗ рд╣реИрдВред рдпрд╣ рд╕рдВрдХрд▓рдХ рдХреЛ рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдпрджрд┐ рд▓рдХреНрд╖реНрдп рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ, рддреЛ рдлрд╝рдВрдХреНрд╢рди рдХреЙрд▓ рдХреЛ рдкрд╛рд░рджрд░реНрд╢реА рд░реВрдк рд╕реЗ рдХреЛрдбрд╛рдВрддрд░рдХ рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЗ рд╕рд╛рде рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдПред

рдиреАрдЪреЗ рдореИрдВ рджреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рддрд░реАрдХреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдЬрд┐рд╕рдореЗрдВ рдЧреЛ рдХрдВрдкрд╛рдЗрд▓рд░ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЕрдзрд┐рдХ рдХреБрд╢рд▓ рдХреЛрдб рдмрдирд╛рддрд╛ рд╣реИред

рдЬрдирд╕рдВрдЦреНрдпрд╛ рдХреА рдЧрдгрдирд╛


рдПрдХ рд╕рдВрдЦреНрдпрд╛ рдХреЗ рдмрд╛рдЗрдирд░реА рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдореЗрдВ рдЗрдХрд╛рдЗрдпреЛрдВ рдХреА рдпрд╣ рд╕рдВрдЦреНрдпрд╛ рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдХреНрд░рд┐рдкреНрдЯреЛрдЧреНрд░рд╛рдлрд╝рд┐рдХ рдЖрджрд┐рдо рд╣реИред рдЪреВрдВрдХрд┐ рдпрд╣ рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдСрдкрд░реЗрд╢рди рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЕрдзрд┐рдХрд╛рдВрд╢ рдЖрдзреБрдирд┐рдХ рд╕реАрдкреАрдпреВ рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рдореЗрдВ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВред
math/bits рдкреИрдХреЗрдЬ OnesCount* рдлрд╝рдВрдХреНрд╢рдВрд╕ рдореЗрдВ рдпрд╣ рдСрдкрд░реЗрд╢рди рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рдЙрдиреНрд╣реЗрдВ рдкрд╣рдЪрд╛рдирд╛ рдФрд░ POPCNT рдкреНрд░реЛрд╕реЗрд╕рд░ POPCNT рд╕рд╛рде рдмрджрд▓ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред

рдпрд╣ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдпрд╣ рдЕрдзрд┐рдХ рдХреБрд╢рд▓ рдХреИрд╕реЗ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдЖрдЗрдП 3 рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрдиреЛрдВ рдХреА рддреБрд▓рдирд╛ рдХрд░реЗрдВред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ рдХреЗрд░реНрдирд┐рдЧрди рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рд╣реИ ред

 func kernighan(x uint64) (count int) { for x > 0 { count++ x &= x - 1 } return count } 

рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЗ рдЪрдХреНрд░реЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдмрд┐рдЯреНрд╕ рд╕реЗрдЯ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЗ рд╕рд╛рде рдореЗрд▓ рдЦрд╛рддреА рд╣реИред рдЕрдзрд┐рдХ рдмрд┐рдЯреНрд╕ - рд▓рдВрдмреЗ рд╕рдордп рддрдХ рдирд┐рд╖реНрдкрд╛рджрди рдХрд╛ рд╕рдордп, рдЬреЛ рд╕рдВрднрд╡рддрдГ рддреАрд╕рд░реЗ рдкрдХреНрд╖ рдХреЗ рдЪреИрдирд▓реЛрдВ рдкрд░ рд╕реВрдЪрдирд╛ рдХреЗ рд░рд┐рд╕рд╛рд╡ рдХреА рдУрд░ рдЬрд╛рддрд╛ рд╣реИред

рджреВрд╕рд░реА рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рд╣реИрдХрд░ рдХреА рдбрд┐рд▓рд╛рдИрдЯ рд╕реЗ рд╣реИ ред

 func hackersdelight(x uint64) uint8 { const m1 = 0b0101010101010101010101010101010101010101010101010101010101010101 const m2 = 0b0011001100110011001100110011001100110011001100110011001100110011 const m4 = 0b0000111100001111000011110000111100001111000011110000111100001111 const h1 = 0b0000000100000001000000010000000100000001000000010000000100000001 x -= (x >> 1) & m1 x = (x & m2) + ((x >> 2) & m2) x = (x + (x >> 4)) & m4 return uint8((x * h1) >> 56) } 

рд╡рд┐рднрд╛рдЬрди рдФрд░ рдЬреАрдд рдХреА рд░рдгрдиреАрддрд┐ рдЗрд╕ рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рд▓рдВрдмреЗ рд╕рдордп рд╕реЗ O (log a) рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИ, рдФрд░ рдмрд┐рдЯреНрд╕ рдХреА рд╕рдВрдЦреНрдпрд╛ рд╕реЗ рд▓рдЧрд╛рддрд╛рд░ рд╕рдордп рдХреЗ рд▓рд┐рдП, рдЬреЛ рдХреНрд░рд┐рдкреНрдЯреЛрдЧреНрд░рд╛рдлреА рдХреЗ рд▓рд┐рдП рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИред рдЪрд▓реЛ math/bits.OnesCount64 рд╕рд╛рде рдкреНрд░рджрд░реНрд╢рди рдХреА рддреБрд▓рдирд╛ рдХрд░реЗрдВ math/bits.OnesCount64 ред

 func BenchmarkKernighan(b *testing.B) { var r int for i := 0; i < bN; i++ { r = kernighan(uint64(i)) } runtime.KeepAlive(r) } func BenchmarkPopcnt(b *testing.B) { var r int for i := 0; i < bN; i++ { r = hackersdelight(uint64(i)) } runtime.KeepAlive(r) } func BenchmarkMathBitsOnesCount64(b *testing.B) { var r int for i := 0; i < bN; i++ { r = bits.OnesCount64(uint64(i)) } runtime.KeepAlive(r) } 

рдИрдорд╛рдирджрд╛рд░ рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рд╣реА рдкреИрд░рд╛рдореАрдЯрд░ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ: 0 рд╕реЗ bN рддрдХ рдХрд╛ рдЕрдиреБрдХреНрд░рдо рдпрд╣ рдХрд░реНрдирд┐рдЧрди рд╡рд┐рдзрд┐ рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рд╕рд╣реА рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рдХрд╛ рд╕рдордп рдЗрдирдкреБрдЯ рддрд░реНрдХ рдХреЗ рдмрд┐рдЯреНрд╕ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЗ рд╕рд╛рде рдмрдврд╝рддрд╛ рд╣реИред тЮЪ

 BenchmarkKernighan-4 100000000 12.9 ns/op BenchmarkPopcnt-4 485724267 2.63 ns/op BenchmarkMathBitsOnesCount64-4 1000000000 0.673 ns/op 

math/bits.OnesCount64 4 рдмрд╛рд░ рдЧрддрд┐ рдореЗрдВ рдЬреАрддрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдпрд╛ рд╣реИрдХрд░ рдиреЗ рд╕рд┐рд░реНрдл рд╣реИрдХрд░реНрд╕ рдбрд┐рд▓рд╛рдЗрдЯ рд╕реЗ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХрд╛ рдмреЗрд╣рддрд░ рдЕрдиреБрдХреВрд▓рди рдХрд┐рдпрд╛ рд╣реИ? рдпрд╣ рдХреЛрдбрд╛рдВрддрд░рдХ рдореЗрдВ рдЖрдиреЗ рдХрд╛ рд╕рдордп рд╣реИред

 go test -c #     

рдЧреЛ рдЯреВрд▓ рдУрдмреНрдЬрдореНрдкрдореНрдк рдХреЛ рдбрд┐рд╕рд╛рдЗрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд░рд▓ рдЙрдкрдпреЛрдЧрд┐рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВ (рдореВрд▓ рд▓реЗрдЦ рдХреЗ рд▓реЗрдЦрдХ рдХреЗ рд╡рд┐рдкрд░реАрдд), рдореИрдВ рдЖрдИрдбреАрдП рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реВрдВрдЧрд╛ред


рдпрд╣рд╛рдВ рдмрд╣реБрдд рдХреБрдЫ рд╣реЛ рд░рд╣рд╛ рд╣реИред рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг: x86 POPCNT рдирд┐рд░реНрджреЗрд╢ рдХреЛ рдкрд░реАрдХреНрд╖рдг рдХреЗ рдХреЛрдб рдореЗрдВ рд╣реА рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЬреИрд╕рд╛ рдХрд┐ рд╣рдордиреЗ рдЙрдореНрдореАрдж рдХреА рдереАред рдпрд╣ рдкреНрд░рддрд┐рдмрдВрдзреЛрдВ рдХреЛ рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рддреЗрдЬ рдмрдирд╛рддрд╛ рд╣реИред

рдпрд╣ рдмреНрд░рд╛рдВрдЪрд┐рдВрдЧ рджрд┐рд▓рдЪрд╕реНрдк рд╣реИред

 cmp cs:runtime_x86HasPOPCNT, 0 jz lable 

рд╣рд╛рдВ, рдпрд╣ рдЕрд╕реЗрдВрдмрд▓рд░ рдкрд░ рдкреЙрд▓реАрдлрд╛рдЗрд▓ рд╣реИред рд╕рднреА рдкреНрд░реЛрд╕реЗрд╕рд░ POPCNT рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред рдЬрдм рдкреНрд░реЛрдЧреНрд░рд╛рдо рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдЖрдкрдХреЗ main рд╕реЗ рдкрд╣рд▓реЗ, runtime.cpuinit рдлрд╝рдВрдХреНрд╢рди рдЬрд╛рдБрдЪрддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдХреЛрдИ рдЖрд╡рд╢реНрдпрдХ рдирд┐рд░реНрджреЗрд╢ рд╣реИ рдФрд░ рдЗрд╕реЗ runtime.x86HasPOPCNT рдореЗрдВ рд╕рд╣реЗрдЬрддрд╛ рд╣реИред рд╣рд░ рдмрд╛рд░ рдХрд╛рд░реНрдпрдХреНрд░рдо рдпрд╣ рдЬрд╛рдБрдЪрддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ POPCNT рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИ, рдпрд╛ рдПрдХ рдкреЙрд▓реАрдлрд╝рд╛рдЗрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ред рдЪреВрдВрдХрд┐ runtime.x86HasPOPCNT рдХрд╛ рдорд╛рдиред runtime.x86HasPOPCNT рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝реЗрд╢рди рдХреЗ рдмрд╛рдж рдирд╣реАрдВ рдмрджрд▓рддрд╛ рд╣реИ, рдкреНрд░реЛрд╕реЗрд╕рд░ рдмреНрд░рд╛рдВрдЪрд┐рдВрдЧ рдХреА рднрд╡рд┐рд╖реНрдпрд╡рд╛рдгреА рдЕрдкреЗрдХреНрд╖рд╛рдХреГрдд рд╕рдЯреАрдХ рд╣реИред

рдкрд░рдорд╛рдгреБ рдХрд╛рдЙрдВрдЯрд░


рдЖрдВрддрд░рд┐рдХ рдХрд╛рд░реНрдп рдирд┐рдпрдорд┐рдд рд░реВрдк рд╕реЗ рдХреЛрдб рд╣реЛрддреЗ рд╣реИрдВ, рд╡реЗ рдПрдХ рдирд┐рд░реНрджреЗрд╢ рд╕реНрдЯреНрд░реАрдо рдореЗрдВ рдЗрдирд▓рд╛рдЗрди рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдо рдкрд░рдорд╛рдгреБ рдкреИрдХреЗрдЬ рдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдЕрдЬреАрдм рд╣рд╕реНрддрд╛рдХреНрд╖рд░реЛрдВ рд╕реЗ рддрд░реАрдХреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдХрд╛рдЙрдВрдЯрд░ рдХрд╛ рдПрдмреНрд╕реНрдЯреНрд░реИрдХреНрд╢рди рдХрд░реЗрдВрдЧреЗред

 package main import ( "sync/atomic" ) type counter uint64 func (c *counter) get() uint64 { return atomic.LoadUint64((*uint64)(c)) } func (c *counter) inc() uint64 { return atomic.AddUint64((*uint64)(c), 1) } func (c *counter) reset() uint64 { return atomic.SwapUint64((*uint64)(c), 0) } func F() uint64 { var c counter c.inc() c.get() return c.reset() } func main() { F() } 

рдХреЛрдИ рд╕реЛрдЪреЗрдЧрд╛ рдХрд┐ рдРрд╕рд╛ рдУрдУрдкреА рдУрд╡рд░рд╣реЗрдб рдЬреЛрдбрд╝ рджреЗрдЧрд╛ред рд▓реЗрдХрд┐рди рдЧреЛ рдЬрд╛рд╡рд╛ рдирд╣реАрдВ рд╣реИ - рдЬрдм рддрдХ рдЖрдк рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдЗрдВрдЯрд░рдлреЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддреЗ рддрдм рддрдХ рднрд╛рд╖рд╛ рд░рдирдЯрд╛рдЗрдо рдореЗрдВ рдмрд╛рдЗрдВрдбрд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддреА рд╣реИред рдКрдкрд░ рджрд┐рдП рдЧрдП рдХреЛрдб рдкреНрд░реЛрд╕реЗрд╕рд░ рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЗ рдПрдХ рдХреБрд╢рд▓ рдкреНрд░рд╡рд╛рд╣ рдореЗрдВ рдврд╣ рдЬрд╛рдПрдВрдЧреЗред рдореБрдЦреНрдп рд░реВрдк рд╕реЗ рдХреИрд╕рд╛ рджрд┐рдЦреЗрдЧрд╛?


рдХреНрд░рдо рдореЗрдВред c.inc lock xadd [rax], 1 рдореЗрдВ рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИ - x86 рдХрд╛ рдкрд░рдорд╛рдгреБ рдЬреЛрдбрд╝ред c.get рд╕рд╛рдорд╛рдиреНрдп рдЪрд▓ рдЕрдиреБрджреЗрд╢ рдмрди рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ x86 рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдкрд░рдорд╛рдгреБ рд╣реИред c.reset рд╢реВрдиреНрдп рд░рдЬрд┐рд╕реНрдЯрд░ рдФрд░ рдореЗрдореЛрд░реА рдХреЗ рдмреАрдЪ xchg рдХрд╛ рдкрд░рдорд╛рдгреБ рд╡рд┐рдирд┐рдордп рдмрди рдЬрд╛рддрд╛ рд╣реИред

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


рдПрдВрдмреЗрдбреЗрдб рдлрд╝рдВрдХреНрд╢рди рдПрдХ рд╕рд╛рдл рд╕рдорд╛рдзрд╛рди рд╣реИ рдЬреЛ рднрд╛рд╖рд╛ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд┐рдП рдмрд┐рдирд╛ рдирд┐рдореНрди-рд╕реНрддрд░реАрдп рд╕рдВрдЪрд╛рд▓рди рддрдХ рдкрд╣реБрдВрдЪ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рдпрджрд┐ рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдХреЗ рдкрд╛рд╕ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕рд┐рдВрдХ / рдкрд░рдорд╛рдгреБ рдЖрджрд┐рдо (рдХреБрдЫ рдПрдЖрд░рдПрдо рд╡реЗрд░рд┐рдПрдВрдЯ рдХреА рддрд░рд╣), рдпрд╛ рдЧрдгрд┐рдд / рдмрд┐рдЯреНрд╕ рд╕реЗ рд╕рдВрдЪрд╛рд▓рди рдирд╣реАрдВ рд╣реИ, рддреЛ рдХрдВрдкрд╛рдЗрд▓рд░ рд╢реБрджреНрдз рдЬрд╛рдиреЗ рдкрд░ рдПрдХ рдкреЙрд▓реАрдлрд╛рдЗрд▓ рд╕рдореНрдорд┐рд▓рд┐рдд рдХрд░рддрд╛ рд╣реИред

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


All Articles