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) }