github.com/egonelbre/exp@v0.0.0-20240430123955-ed1d3aa93911/sse/sse_test.go (about) 1 package sse 2 3 import ( 4 "math/rand" 5 "testing" 6 "testing/quick" 7 ) 8 9 func same(a, b []uint32) bool { 10 for i := range a { 11 if a[i] != b[i] { 12 return false 13 } 14 } 15 return true 16 } 17 18 type op func(a, b []uint32) 19 20 func testOp(t *testing.T, fast, slow op) { 21 f := func(dst1, src []uint32) bool { 22 dst2 := make([]uint32, len(dst1)) 23 copy(dst2, dst1) 24 25 slow(dst2, src) 26 fast(dst1, src) 27 28 return same(dst1, dst2) 29 } 30 31 if err := quick.Check(f, nil); err != nil { 32 t.Error(err) 33 } 34 } 35 36 func simpleTest(t *testing.T, fast, slow op) { 37 dst := []uint32{5, 4, 3, 2, 1, 8, 2, 8, 3, 3, 2, 5, 8, 5, 1, 8, 2, 8, 3, 3, 2, 5, 8} 38 src := []uint32{1, 2, 5, 7, 5, 1, 4, 1, 5, 0, 5, 1, 1, 5, 1, 4, 1, 5, 0, 5, 1} 39 40 dst_fast := make([]uint32, len(dst)) 41 dst_slow := make([]uint32, len(dst)) 42 copy(dst_fast, dst) 43 copy(dst_slow, dst) 44 45 fast(dst_fast, src) 46 slow(dst_slow, src) 47 48 if !same(dst_slow, dst_fast) { 49 t.Errorf("failed\ndst\t%v\nsrc\t%v\nexp\t%v\ngot\t%v", dst, src, dst_slow, dst_fast) 50 } 51 } 52 53 func TestAddU32_ASM_Simple(t *testing.T) { simpleTest(t, AddU32_ASM, AddU32_Slow) } 54 func TestSubU32_ASM_Simple(t *testing.T) { simpleTest(t, SubU32_ASM, SubU32_Slow) } 55 func TestMulU32_ASM_Simple(t *testing.T) { simpleTest(t, MulU32_ASM, MulU32_Slow) } 56 57 func TestAddU32_ASM_Quick(t *testing.T) { testOp(t, AddU32_ASM, AddU32_Slow) } 58 func TestSubU32_ASM_Quick(t *testing.T) { testOp(t, SubU32_ASM, SubU32_Slow) } 59 func TestMulU32_ASM_Quick(t *testing.T) { testOp(t, MulU32_ASM, MulU32_Slow) } 60 61 func TestAddU32_SSE_Simple(t *testing.T) { simpleTest(t, AddU32_SSE, AddU32_Slow) } 62 func TestSubU32_SSE_Simple(t *testing.T) { simpleTest(t, SubU32_SSE, SubU32_Slow) } 63 func TestMulU32_SSE_Simple(t *testing.T) { simpleTest(t, MulU32_SSE, MulU32_Slow) } 64 65 func TestAddU32_SSE_Quick(t *testing.T) { testOp(t, AddU32_SSE, AddU32_Slow) } 66 func TestSubU32_SSE_Quick(t *testing.T) { testOp(t, SubU32_SSE, SubU32_Slow) } 67 func TestMulU32_SSE_Quick(t *testing.T) { testOp(t, MulU32_SSE, MulU32_Slow) } 68 69 func benchpair(size int) ([]uint32, []uint32) { 70 rng := rand.NewSource(0) 71 dst := make([]uint32, size) 72 src := make([]uint32, size) 73 for i := range dst { 74 dst[i] = uint32(rng.Int63()) 75 src[i] = uint32(rng.Int63()) 76 } 77 return dst, src 78 } 79 80 func bench(b *testing.B, op op) { 81 dst, src := benchpair(1 << 20) 82 b.SetBytes(4 << 20) 83 b.ResetTimer() 84 for i := 0; i < b.N; i++ { 85 op(dst, src) 86 } 87 } 88 89 func BenchmarkAddU32_Slow(b *testing.B) { bench(b, AddU32_Slow) } 90 func BenchmarkAddU32_ASM(b *testing.B) { bench(b, AddU32_ASM) } 91 func BenchmarkAddU32_SSE(b *testing.B) { bench(b, AddU32_SSE) } 92 93 func BenchmarkSubU32_Slow(b *testing.B) { bench(b, SubU32_Slow) } 94 func BenchmarkSubU32_ASM(b *testing.B) { bench(b, SubU32_ASM) } 95 func BenchmarkSubU32_SSE(b *testing.B) { bench(b, SubU32_SSE) } 96 97 func BenchmarkMulU32_Slow(b *testing.B) { bench(b, MulU32_Slow) } 98 func BenchmarkMulU32_ASM(b *testing.B) { bench(b, MulU32_ASM) } 99 func BenchmarkMulU32_SSE(b *testing.B) { bench(b, MulU32_SSE) }