Skip to content

Instantly share code, notes, and snippets.

@ttsugriy
Created May 15, 2021 19:03
Show Gist options
  • Save ttsugriy/03418a8a747b140d7449ece7d123d759 to your computer and use it in GitHub Desktop.
Save ttsugriy/03418a8a747b140d7449ece7d123d759 to your computer and use it in GitHub Desktop.
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