Skip to content

Commit

Permalink
Basic chore cleanups of tests and benchmarks (#66)
Browse files Browse the repository at this point in the history
* Upgrade cpuid, regen buildtags

* Move all uses of cpuid to one place, adjust benchmarks

* Rename SIMD functions to match instruction set

* One more rename, align arch-specific files
  • Loading branch information
ribasushi authored Jan 30, 2023
1 parent 99e45fa commit d9c3aea
Show file tree
Hide file tree
Showing 14 changed files with 94 additions and 90 deletions.
6 changes: 5 additions & 1 deletion cpuid_other.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ import (
"github.com/klauspost/cpuid/v2"
)

var (
hasIntelSha = runtime.GOARCH == "amd64" && cpuid.CPU.Supports(cpuid.SHA, cpuid.SSSE3, cpuid.SSE4)
hasAvx512 = cpuid.CPU.Supports(cpuid.AVX512F, cpuid.AVX512DQ, cpuid.AVX512BW, cpuid.AVX512VL)
)

func hasArmSha2() bool {
if cpuid.CPU.Has(cpuid.SHA2) {
return true
Expand All @@ -42,5 +47,4 @@ func hasArmSha2() bool {
return false
}
return bytes.Contains(cpuInfo, []byte(sha256Feature))

}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ module github.com/minio/sha256-simd

go 1.13

require github.com/klauspost/cpuid/v2 v2.0.6
require github.com/klauspost/cpuid/v2 v2.2.3
6 changes: 4 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
github.com/klauspost/cpuid/v2 v2.0.6 h1:dQ5ueTiftKxp0gyjKSx5+8BtPWkyQbd95m8Gys/RarI=
github.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU=
github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e h1:CsOuNlbOuf0mzxJIefr6Q4uAUetRUwZE4qt7VfzP+xo=
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
51 changes: 20 additions & 31 deletions sha256.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@ import (
"crypto/sha256"
"encoding/binary"
"hash"
"runtime"

"github.com/klauspost/cpuid/v2"
)

// Size - The size of a SHA256 checksum in bytes.
Expand Down Expand Up @@ -68,42 +65,34 @@ func (d *digest) Reset() {
type blockfuncType int

const (
blockfuncGeneric blockfuncType = iota
blockfuncSha blockfuncType = iota
blockfuncArm blockfuncType = iota
blockfuncStdlib blockfuncType = iota
blockfuncIntelSha
blockfuncArmSha2
blockfuncForceGeneric = -1
)

var blockfunc blockfuncType

func init() {
blockfunc = blockfuncGeneric
switch {
case hasSHAExtensions():
blockfunc = blockfuncSha
case hasIntelSha:
blockfunc = blockfuncIntelSha
case hasArmSha2():
blockfunc = blockfuncArm
default:
blockfunc = blockfuncGeneric
blockfunc = blockfuncArmSha2
}
}

var avx512 = cpuid.CPU.Supports(cpuid.AVX512F, cpuid.AVX512DQ, cpuid.AVX512BW, cpuid.AVX512VL)

// hasSHAExtensions return whether the cpu supports SHA extensions.
func hasSHAExtensions() bool {
return cpuid.CPU.Supports(cpuid.SHA, cpuid.SSSE3, cpuid.SSE4) && runtime.GOARCH == "amd64"
}

// New returns a new hash.Hash computing the SHA256 checksum.
func New() hash.Hash {
if blockfunc != blockfuncGeneric {
d := new(digest)
d.Reset()
return d
if blockfunc == blockfuncStdlib {
// Fallback to the standard golang implementation
// if no features were found.
return sha256.New()
}
// Fallback to the standard golang implementation
// if no features were found.
return sha256.New()

d := new(digest)
d.Reset()
return d
}

// Sum256 - single caller sha256 helper
Expand Down Expand Up @@ -272,11 +261,11 @@ func (d *digest) checkSum() (digest [Size]byte) {
}

func block(dig *digest, p []byte) {
if blockfunc == blockfuncSha {
blockShaGo(dig, p)
} else if blockfunc == blockfuncArm {
blockArmGo(dig, p)
} else if blockfunc == blockfuncGeneric {
if blockfunc == blockfuncIntelSha {
blockIntelShaGo(dig, p)
} else if blockfunc == blockfuncArmSha2 {
blockArmSha2Go(dig, p)
} else {
blockGeneric(dig, p)
}
}
Expand Down
38 changes: 22 additions & 16 deletions sha256_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ import (
"fmt"
"strings"
"testing"

"github.com/klauspost/cpuid/v2"
)

type sha256Test struct {
Expand Down Expand Up @@ -2217,7 +2215,7 @@ func TestGolden(t *testing.T) {
}()

if true {
blockfunc = blockfuncGeneric
blockfunc = blockfuncForceGeneric
for _, g := range golden {
s := fmt.Sprintf("%x", Sum256([]byte(g.in)))
if Sum256([]byte(g.in)) != g.out {
Expand All @@ -2226,8 +2224,8 @@ func TestGolden(t *testing.T) {
}
}

if cpuid.CPU.Supports(cpuid.SHA, cpuid.SSSE3, cpuid.SSE4) {
blockfunc = blockfuncSha
if hasIntelSha {
blockfunc = blockfuncIntelSha
for _, g := range golden {
s := fmt.Sprintf("%x", Sum256([]byte(g.in)))
if Sum256([]byte(g.in)) != g.out {
Expand All @@ -2237,7 +2235,7 @@ func TestGolden(t *testing.T) {
}

if hasArmSha2() {
blockfunc = blockfuncArm
blockfunc = blockfuncArmSha2
for _, g := range golden {
s := fmt.Sprintf("%x", Sum256([]byte(g.in)))
if Sum256([]byte(g.in)) != g.out {
Expand Down Expand Up @@ -2269,27 +2267,34 @@ func benchmarkSize(b *testing.B, size int) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
bench.Reset()
bench.Write(buf[:size])
bench.Write(buf)
bench.Sum(sum[:0])
}
}

func BenchmarkHash(b *testing.B) {
algos := []struct {
type alg struct {
n string
t blockfuncType
f bool
}{
{"SHA_", blockfuncSha, hasSHAExtensions()},
{"GEN_", blockfuncGeneric, true},
}
algos := make([]alg, 0, 2)

algos = append(algos, alg{"Generic", blockfuncForceGeneric})
if hasIntelSha {
algos = append(algos, alg{"IntelSHA", blockfuncIntelSha})
}
if hasArmSha2() {
algos = append(algos, alg{"ArmSha2", blockfuncArmSha2})
}
algos = append(algos, alg{"GoStdlib", blockfuncStdlib})

sizes := []struct {
n string
f func(*testing.B, int)
s int
}{
{"8Bytes", benchmarkSize, 1 << 3},
{"64Bytes", benchmarkSize, 1 << 6},
{"1K", benchmarkSize, 1 << 10},
{"8K", benchmarkSize, 1 << 13},
{"1M", benchmarkSize, 1 << 20},
Expand All @@ -2298,14 +2303,15 @@ func BenchmarkHash(b *testing.B) {
}

for _, a := range algos {
if a.f {
blockfuncSaved := blockfunc
func() {
orig := blockfunc
defer func() { blockfunc = orig }()

blockfunc = a.t
for _, y := range sizes {
s := a.n + "/" + y.n
b.Run(s, func(b *testing.B) { y.f(b, y.s) })
}
blockfunc = blockfuncSaved
}
}()
}
}
3 changes: 2 additions & 1 deletion sha256blockAvx512_amd64.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//+build !noasm,!appengine,gc
//go:build !noasm && !appengine && gc
// +build !noasm,!appengine,gc

/*
* Minio Cloud Storage, (C) 2017 Minio, Inc.
Expand Down
19 changes: 10 additions & 9 deletions sha256blockAvx512_amd64_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//+build !noasm,!appengine,gc
//go:build !noasm && !appengine && gc
// +build !noasm,!appengine,gc

/*
* Minio Cloud Storage, (C) 2017 Minio, Inc.
Expand Down Expand Up @@ -31,7 +32,7 @@ import (

func TestGoldenAVX512(t *testing.T) {

if !avx512 {
if !hasAvx512 {
t.SkipNow()
return
}
Expand Down Expand Up @@ -75,7 +76,7 @@ func initDigests() *[512]byte {

func testSha256Avx512(t *testing.T, offset, padding int) [16][]byte {

if !avx512 {
if !hasAvx512 {
t.SkipNow()
return [16][]byte{}
}
Expand Down Expand Up @@ -118,7 +119,7 @@ func TestAvx512_3Blocks(t *testing.T) { testSha256Avx512(t, 47, 55) }

func TestAvx512_MixedBlocks(t *testing.T) {

if !avx512 {
if !hasAvx512 {
t.SkipNow()
return
}
Expand Down Expand Up @@ -153,7 +154,7 @@ func TestAvx512_MixedBlocks(t *testing.T) {

func TestAvx512_MixedWithNilBlocks(t *testing.T) {

if !avx512 {
if !hasAvx512 {
t.SkipNow()
return
}
Expand Down Expand Up @@ -200,7 +201,7 @@ func TestAvx512_MixedWithNilBlocks(t *testing.T) {

func TestAvx512Server(t *testing.T) {

if !avx512 {
if !hasAvx512 {
t.SkipNow()
return
}
Expand Down Expand Up @@ -251,7 +252,7 @@ func TestAvx512Server(t *testing.T) {

func TestAvx512Digest(t *testing.T) {

if !avx512 {
if !hasAvx512 {
t.SkipNow()
return
}
Expand Down Expand Up @@ -295,7 +296,7 @@ func benchmarkAvx512SingleCore(h512 []hash.Hash, body []byte) {

func benchmarkAvx512(b *testing.B, size int) {

if !avx512 {
if !hasAvx512 {
b.SkipNow()
return
}
Expand Down Expand Up @@ -325,7 +326,7 @@ func BenchmarkAvx512_10M(b *testing.B) { benchmarkAvx512(b, 10*1024*1024) }

func benchmarkAvx512MultiCore(b *testing.B, size, cores int) {

if !avx512 {
if !hasAvx512 {
b.SkipNow()
return
}
Expand Down
6 changes: 0 additions & 6 deletions sha256blockSha_amd64.go

This file was deleted.

14 changes: 9 additions & 5 deletions sha256block_amd64.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//+build !noasm,!appengine,gc
//go:build !noasm && !appengine && gc
// +build !noasm,!appengine,gc

/*
* Minio Cloud Storage, (C) 2016 Minio, Inc.
Expand All @@ -18,10 +19,13 @@

package sha256

func blockArmGo(dig *digest, p []byte) {
panic("blockArmGo called unexpectedly")
func blockArmSha2Go(dig *digest, p []byte) {
panic("blockArmSha2Go called unexpectedly")
}

func blockShaGo(dig *digest, p []byte) {
blockSha(&dig.h, p)
//go:noescape
func blockIntelSha(h *[8]uint32, message []uint8)

func blockIntelShaGo(dig *digest, p []byte) {
blockIntelSha(&dig.h, p)
}
2 changes: 1 addition & 1 deletion sha256blockSha_amd64.s → sha256block_amd64.s
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ GLOBL SHUF_MASK<>(SB), RODATA|NOPTR, $16
// X13 saved hash state // CDGH
// X15 data shuffle mask (constant)

TEXT ·blockSha(SB), NOSPLIT, $0-32
TEXT ·blockIntelSha(SB), NOSPLIT, $0-32
MOVQ h+0(FP), DX
MOVQ message_base+8(FP), SI
MOVQ message_len+16(FP), DI
Expand Down
11 changes: 6 additions & 5 deletions sha256blockSha_amd64_test.go → sha256block_amd64_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//+build !noasm,!appengine,gc
//go:build !noasm && !appengine && gc
// +build !noasm,!appengine,gc

package sha256

Expand All @@ -20,7 +21,7 @@ func sha256hash(m []byte) (r [32]byte) {
h[6] = 0x1f83d9ab
h[7] = 0x5be0cd19

blockSha(&h, m)
blockIntelSha(&h, m)
l0 := len(m)
l := l0 & (BlockSize - 1)
m = m[l0-l:]
Expand All @@ -31,7 +32,7 @@ func sha256hash(m []byte) (r [32]byte) {
k[l] = 0x80

if l >= 56 {
blockSha(&h, k[:])
blockIntelSha(&h, k[:])
binary.LittleEndian.PutUint64(k[0:8], 0)
binary.LittleEndian.PutUint64(k[8:16], 0)
binary.LittleEndian.PutUint64(k[16:24], 0)
Expand All @@ -41,7 +42,7 @@ func sha256hash(m []byte) (r [32]byte) {
binary.LittleEndian.PutUint64(k[48:56], 0)
}
binary.BigEndian.PutUint64(k[56:64], uint64(l0)<<3)
blockSha(&h, k[:])
blockIntelSha(&h, k[:])

binary.BigEndian.PutUint32(r[0:4], h[0])
binary.BigEndian.PutUint32(r[4:8], h[1])
Expand Down Expand Up @@ -71,7 +72,7 @@ func TestSha0(t *testing.T) {
}

func TestSha1(t *testing.T) {
if hasSHAExtensions() && !runTestSha(sha256hash) {
if hasIntelSha && !runTestSha(sha256hash) {
t.Errorf("FAILED")
}
}
Loading

0 comments on commit d9c3aea

Please sign in to comment.