Skip to content

Commit

Permalink
add a benchmark test for strash key spread
Browse files Browse the repository at this point in the history
  • Loading branch information
ecordell committed Aug 25, 2021
1 parent e42accb commit d371b23
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 8 deletions.
4 changes: 3 additions & 1 deletion logic/c.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,8 @@ func (p *C) grow() {
p.strash = strash
}

var strashCode = strasher

// this is sortof fnv-1a, but we do not do it byte wise
// instead lit-wise (which is 4x wider) and there is no offset.
// It gives the fewest collisions of the hashes we tried.
Expand All @@ -384,6 +386,6 @@ func (p *C) grow() {
// more collisions. It was actually faster than the above,
// the increase of collisions was compensated for by
// faster computation (less multiplies).
func strashCode(a, b z.Lit) uint32 {
func strasher(a, b z.Lit) uint32 {
return 16777619 * ^uint32(b) * 16777619 * ^uint32(a)
}
97 changes: 90 additions & 7 deletions logic/c_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@

package logic

import(
import (
"fmt"
"hash/fnv"
"log"
"math/rand"
"testing"
"time"

"github.com/go-air/gini"
"github.com/go-air/gini/gen"
Expand Down Expand Up @@ -169,12 +171,93 @@ func (a *cAdder) Add(m z.Lit) {
a.f = a.c.And(a.f, clause)
}

// spread returns a number [0,1] that indicates how full the strash array is
// a value of 0 means that no entries are filled, a value of 1 means that all entries are filled
// a higher value indicates better spread of the hash keys over the array
func spread(c *C) float64 {
filled := 0
for _, v := range c.strash {
if v != 0 {
filled++
}
}
return float64(filled) / float64(len(c.strash))
}

func BenchmarkStrash(b *testing.B) {
for i := 0; i < b.N; i++ {
circuit := NewC()
ca := &cAdder{
c: circuit,
f: circuit.T}
gen.Rand3Cnf(ca, 100, 300)
var spreadSum float64
strashFuncs := map[string]func(a, b z.Lit) uint32{
"shift-negate-multiply": func(a, b z.Lit) uint32 {
return uint32(^(a << 13) * b)
},
"fastutil-phimix": func(a, b z.Lit) uint32 {
h := uint32(a * b * 0x9E3779B9)
return h ^ (h >> 16)
},
"fnv-litwise-no-offset": func(a, b z.Lit) uint32 {
return 16777619 * ^uint32(b) * 16777619 * ^uint32(a)
},
"fnv-litwise": func(a, b z.Lit) uint32 {
return 2166136261 + 16777619 * ^uint32(b) * 16777619 * ^uint32(a)
},
"fnv": func(a, b z.Lit) uint32 {
hasher := fnv.New32()
hasher.Write([]byte{byte(a), byte(a >> 8), byte(a >> 16), byte(a >> 24), byte(b), byte(b >> 8), byte(b >> 16), byte(b >> 24)})
return hasher.Sum32()
},
"fnv-direct": func(a, b z.Lit) uint32 {
hash := uint32(2166136261)
prime := uint32(16777619)
hash = (hash * prime) ^ uint32(a)
hash = (hash * prime) ^ uint32(a>>8)
hash = (hash * prime) ^ uint32(a>>16)
hash = (hash * prime) ^ uint32(a>>24)
hash = (hash * prime) ^ uint32(b)
hash = (hash * prime) ^ uint32(b>>8)
hash = (hash * prime) ^ uint32(b>>16)
hash = (hash * prime) ^ uint32(b>>24)
return hash
},
"add": func(a, b z.Lit) uint32 {
return uint32(a + b)
},
"mult": func(a, b z.Lit) uint32 {
return uint32(a * b)
},
"and": func(a, b z.Lit) uint32 {
return uint32(a & b)
},
"or": func(a, b z.Lit) uint32 {
return uint32(a | b)
},
"64bit->32bit magic number hash": func(a, b z.Lit) uint32 {
return uint32((uint64(a)<<32 | uint64(b)) * 0x8000000080000001 >> 32)
},
"2x32bit->16bit magic number hash, both msb": func(a, b z.Lit) uint32 {
return (((uint32(a) * 0x80008001) >> 16) << 16) | ((uint32(b) * 0x80008001) >> 16)
},
"2x32bit->16bit magic number hash, a msb, b lsb": func(a, b z.Lit) uint32 {
return (((uint32(a) * 0x80008001) >> 16) << 16) | ((uint32(b) * 0x80008001) >> 16)
},
}
for name, strash := range strashFuncs {
strashCode = strash
for n := 1; n <= 1000; n *= 10 {
b.Run(fmt.Sprintf("%s-%d", name, n), func(b *testing.B) {
spreadSum = 0
for i := 0; i < b.N; i++ {
circuit := NewC()
ca := &cAdder{
c: circuit,
f: circuit.T}
gen.Seed(time.Now().Unix())
b.StartTimer()
gen.Rand3Cnf(ca, n*100, n*300)
b.StopTimer()
spreadSum += spread(circuit)
}
b.ReportMetric(spreadSum/float64(b.N), "spread")
})
}
}
}

0 comments on commit d371b23

Please sign in to comment.