123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 |
- // dotproduct_test.go
- package dotproduct
- import (
- "runtime"
- "sync/atomic"
- "testing"
- "unsafe"
- "golang.org/x/sys/cpu"
- )
- func TestAVX2hasAVX(t *testing.T) {
- if runtime.GOARCH == "amd64" {
- if cpu.X86.HasAVX2 && !cpu.X86.HasAVX {
- t.Fatal("HasAVX expected true, got false")
- } else if !cpu.X86.HasAVX2 {
- t.Log("HasAVX2=False")
- }
- }
- }
- func TestAVX512HasAVX2AndAVX(t *testing.T) {
- if runtime.GOARCH == "amd64" {
- if cpu.X86.HasAVX512 && !cpu.X86.HasAVX {
- t.Fatal("HasAVX expected true, got false")
- }
- if cpu.X86.HasAVX512 && !cpu.X86.HasAVX2 {
- t.Fatal("HasAVX2 expected true, got false")
- }
- if !cpu.X86.HasAVX512 {
- t.Log("HasAVX512=False")
- }
- }
- }
- func DotProduct(a []int32, b []int32, N int32) (sum int32) {
- //N := len(a)
- for i := int32(0); i < N; i++ {
- sum += a[i] * b[i]
- }
- return
- }
- func TestSumAsm(t *testing.T) {
- if runtime.GOARCH == "amd64" {
- d3 := make([]uint64, 24)
- var sumGo uint64
- for i := 0; i < 24; i++ {
- d3[i] = uint64(i + 1)
- sumGo = sumGo + d3[i]
- }
- sumAsm := Sum(d3)
- t.Log("sumGo ", sumGo, ", sumAsm ", sumAsm)
- } else {
- t.Skip("test case *TestSumAsm* not applicable")
- }
- }
- func TestDotProductAsm(t *testing.T) {
- if runtime.GOARCH == "amd64" {
- const len32 = 24
- d1 := make([]int32, len32)
- d2 := make([]int32, len32)
- for i := 0; i < len32; i++ {
- d1[i] = int32(i + 1)
- d2[i] = int32(2 * i)
- }
- sumGo := DotProduct(d1, d2, len32)
- sumAsm := DotProductAsm(d1, d2, len32)
- t.Log("DotProductGo ", sumGo, ", DotProductAsm ", sumAsm)
- } else {
- t.Skip("test case *TestDotProductAsm* not applicable")
- }
- }
- func TestDotProductAsmAvx(t *testing.T) {
- if runtime.GOARCH == "amd64" && cpu.X86.HasAVX2 {
- const len32 = 32
- d1 := make([]int32, len32)
- d2 := make([]int32, len32)
- for i := 0; i < len32; i++ {
- d1[i] = int32(i + 1)
- d2[i] = int32(2 * i)
- }
- sumGo := DotProduct(d1, d2, len32)
- sumAvx := DotProductAsmAvx(d1, d2, len32)
- t.Log("DotProductGo ", sumGo, ", DotProductAvx ", sumAvx)
- } else {
- t.Skip("test case *TestDotProductAsmAvx* not applicable")
- }
- }
- func BenchmarkSum(b *testing.B) {
- const len32 = 4096
- d1 := make([]uint64, len32)
- for i := 0; i < len32; i++ {
- d1[i] = uint64(i + 1)
- }
- var sum2 uint64 = 0
- b.SetBytes(int64(len32 * unsafe.Sizeof(uint64(0))))
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- sum2 += SumGo(d1) % len32
- }
- }
- func BenchmarkSumParallel(b *testing.B) {
- const len32 = 4096
- d1 := make([]uint64, len32)
- for i := 0; i < len32; i++ {
- d1[i] = uint64(i + 1)
- }
- b.SetBytes(int64(len32 * unsafe.Sizeof(uint64(0))))
- b.ResetTimer()
- b.RunParallel(func(pb *testing.PB) {
- for pb.Next() {
- var sum2 uint64 = 0
- sum2 += SumGo(d1) % len32
- }
- })
- }
- func BenchmarkSumAsm(b *testing.B) {
- if runtime.GOARCH == "amd64" {
- const len32 = 4096
- d1 := make([]uint64, len32)
- for i := 0; i < len32; i++ {
- d1[i] = uint64(i + 1)
- }
- var sum2 uint64 = 0
- b.SetBytes(int64(len32 * unsafe.Sizeof(uint64(0))))
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- sum2 += Sum(d1) % len32
- }
- } else {
- b.Skip("test case *BenchmarkSumAsm* not applicable")
- }
- }
- func BenchmarkSumAsmParallel(b *testing.B) {
- if runtime.GOARCH == "amd64" {
- const len32 = 4096
- d1 := make([]uint64, len32)
- for i := 0; i < len32; i++ {
- d1[i] = uint64(i + 1)
- }
- //glob := b.N
- b.SetBytes(int64(len32 * unsafe.Sizeof(uint64(0))))
- b.ResetTimer()
- b.RunParallel(func(pb *testing.PB) {
- for pb.Next() {
- var sum2 uint64 = 0
- //for i := 0; i < 24; i++ {
- sum2 += Sum(d1) % len32
- //}
- }
- })
- } else {
- b.Skip("test case *BenchmarkSumAsm* not applicable")
- }
- }
- func SumGo(a []uint64) (sum uint64) {
- N := len(a)
- for i := 0; i < N; i++ {
- sum += a[i]
- }
- return
- }
- func BenchmarkDotProduct(b *testing.B) {
- const len32 = 1024
- d1 := make([]int32, len32)
- d2 := make([]int32, len32)
- for i := 0; i < len32; i++ {
- d1[i] = int32(i + 1)
- d2[i] = int32(2 * i)
- }
- var sum2 int32 = 0
- b.SetBytes(int64(len32 * unsafe.Sizeof(int32(0))))
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- sum2 += DotProduct(d1, d2, len32) % len32
- }
- }
- func BenchmarkDotProductAsm(b *testing.B) {
- if runtime.GOARCH == "amd64" {
- const len32 = 1024
- d1 := make([]int32, len32)
- d2 := make([]int32, len32)
- for i := 0; i < len32; i++ {
- d1[i] = int32(i + 1)
- d2[i] = int32(2 * i)
- }
- var sum2 int32 = 0
- b.SetBytes(int64(len32 * unsafe.Sizeof(int32(0))))
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- sum2 += DotProductAsm(d1, d2, len32) % len32
- }
- } else {
- b.Skip("test case *BenchmarkDotProductAsm* not applicable")
- }
- }
- func BenchmarkDotProductAsmAvx2(b *testing.B) {
- if runtime.GOARCH == "amd64" && cpu.X86.HasAVX2 {
- const len32 = 1024
- d1 := make([]int32, len32)
- d2 := make([]int32, len32)
- for i := 0; i < len32; i++ {
- d1[i] = int32(i + 1)
- d2[i] = int32(2 * i)
- }
- var sum2 int32 = 0
- b.SetBytes(int64(len32 * unsafe.Sizeof(int32(0))))
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- sum2 += DotProductAsmAvx(d1, d2, len32) % len32
- }
- } else {
- b.Skip("test case *BenchmarkDotProductAsmAvx2* not applicable")
- }
- }
- func BenchmarkDotProductAsmAvx2Parallel(b *testing.B) {
- if runtime.GOARCH == "amd64" && cpu.X86.HasAVX2 {
- const len32 = 1024
- d1 := make([]int32, len32)
- d2 := make([]int32, len32)
- for i := 0; i < len32; i++ {
- d1[i] = int32(i + 1)
- d2[i] = int32(2 * i)
- }
- b.SetBytes(int64(len32 * unsafe.Sizeof(int32(0))))
- b.ResetTimer()
- b.RunParallel(func(pb *testing.PB) {
- for pb.Next() {
- var sum2 int32 = 0
- //for i := 0; i < 24; i++ {
- sum2 += DotProductAsmAvx(d1, d2, len32) % len32
- //}
- }
- })
- } else {
- b.Skip("test case *BenchmarkDotProductAsmAvx2* not applicable")
- }
- }
- func BenchmarkHowItWorksParallel(b *testing.B) {
- procs := uint32(0)
- iters := uint64(0)
- //b.SetParallelism(3) //number of goroutine to each b.RunParallel
- b.SetBytes(int64(4 * unsafe.Sizeof(uint64(0))))
- b.ResetTimer()
- b.RunParallel(func(pb *testing.PB) {
- atomic.AddUint32(&procs, 1)
- for pb.Next() {
- atomic.AddUint64(&iters, 1)
- }
- })
- b.Log("goroutine count :", procs, ", retrial count :", iters)
- }
|