Created
May 15, 2021 19:03
-
-
Save ttsugriy/03418a8a747b140d7449ece7d123d759 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"math/bits" | |
"testing" | |
) | |
//go:noinline | |
func kernighan(x uint64) int { | |
var count int | |
for ; x > 0; x &= (x - 1) { | |
count++ | |
} | |
return count | |
} | |
const m0 = 0x5555555555555555 // 01010101 ... | |
const m1 = 0x3333333333333333 // 00110011 ... | |
const m2 = 0x0f0f0f0f0f0f0f0f // 00001111 ... | |
//go:noinline | |
func parallel_summing(x uint64) int { | |
const m = 1<<64 - 1 | |
x = x>>1&(m0&m) + x&(m0&m) | |
x = x>>2&(m1&m) + x&(m1&m) | |
x = (x>>4 + x) & (m2 & m) | |
x += x >> 8 | |
x += x >> 16 | |
x += x >> 32 | |
return int(x) & (1<<7 - 1) | |
} | |
var pop8tab = [256]uint8{ | |
0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, | |
0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, | |
0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, | |
0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, | |
0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, | |
0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, | |
0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, | |
0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, | |
0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, | |
0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, | |
0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, | |
0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, | |
0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, | |
0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, | |
0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, | |
0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x05, 0x06, 0x06, 0x07, 0x06, 0x07, 0x07, 0x08, | |
} | |
//go:noinline | |
func pop8_table(x uint64) int { | |
return int(pop8tab[x>>56&0xff] + pop8tab[x>>48&0xff] + pop8tab[x>>40&0xff] + pop8tab[x>>32&0xff] + pop8tab[x>>24&0xff] + pop8tab[x>>16&0xff] + pop8tab[x>>8&0xff] + pop8tab[x&0xff]) | |
} | |
const c1 = 0x5555555555555555 | |
const c2 = 0x3333333333333333 | |
const c4 = 0x0F0F0F0F0F0F0F0F | |
//go:noinline | |
func wilkes_wheeler_gill(x uint64) int { | |
x -= (x >> 1) & c1 | |
x = ((x >> 2) & c2) + (x & c2) | |
x = (x + (x >> 4)) & c4 | |
x *= 0x0101010101010101 | |
return int(x >> 56) | |
} | |
//go:noinline | |
func pop_count(x uint64) int { | |
return bits.OnesCount64(x) | |
} | |
func popcnt(x uint64) int | |
var x uint64 = 0xffffffffffffffff | |
// var x uint64 = 0 | |
var result int | |
func BenchmarkPopCountKernighan(b *testing.B) { | |
var cnt int | |
for i := 0; i < b.N; i++ { | |
cnt += kernighan(x) | |
} | |
result += cnt | |
} | |
func BenchmarkPopCountParallelSumming(b *testing.B) { | |
var cnt int | |
for i := 0; i < b.N; i++ { | |
cnt += parallel_summing(x) | |
} | |
result += cnt | |
} | |
func BenchmarkPopCountPop8Tab(b *testing.B) { | |
var cnt int | |
for i := 0; i < b.N; i++ { | |
cnt += pop8_table(x) | |
} | |
result += cnt | |
} | |
func BenchmarkPopCountWilkesWheelerGill(b *testing.B) { | |
var cnt int | |
for i := 0; i < b.N; i++ { | |
cnt += wilkes_wheeler_gill(x) | |
} | |
result += cnt | |
} | |
func BenchmarkPopCountMathBits(b *testing.B) { | |
var cnt int | |
for i := 0; i < b.N; i++ { | |
cnt += pop_count(x) | |
} | |
result += cnt | |
} | |
func BenchmarkPopCountPOPCNTAsm(b *testing.B) { | |
var cnt int | |
for i := 0; i < b.N; i++ { | |
cnt += popcnt(x) | |
} | |
result += cnt | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment