github.com/egonelbre/exp@v0.0.0-20240430123955-ed1d3aa93911/bench/dot/main_test.go (about)

     1  package main
     2  
     3  import (
     4  	"testing"
     5  	"unsafe"
     6  )
     7  
     8  func Dot1(a, b []float64) float64 {
     9  	var sum float64
    10  	for i := 0; i < len(a); i += 4 {
    11  		s0 := a[i] * b[i]
    12  		s1 := a[i+1] * b[i+1]
    13  		s2 := a[i+2] * b[i+2]
    14  		s3 := a[i+3] * b[i+3]
    15  		sum += s0 + s1 + s2 + s3
    16  	}
    17  	return sum
    18  }
    19  
    20  func Dot2(a, b []float64) float64 {
    21  	type F64x4 struct{ X, Y, Z, W float64 }
    22  
    23  	xs := unsafe.Slice((*F64x4)(unsafe.Pointer(unsafe.SliceData(a))), len(a)/4)
    24  	ys := unsafe.Slice((*F64x4)(unsafe.Pointer(unsafe.SliceData(b))), len(b)/4)
    25  
    26  	if len(xs) != len(ys) {
    27  		return 0
    28  	}
    29  
    30  	var x, y, z, w float64
    31  
    32  	for i := range xs {
    33  		x += xs[i].X * ys[i].X
    34  		y += xs[i].Y * ys[i].Y
    35  		z += xs[i].Z * ys[i].Z
    36  		w += xs[i].W * ys[i].W
    37  	}
    38  
    39  	// TODO: handle leftover stuff
    40  
    41  	return x + y + z + w
    42  }
    43  
    44  func Dot3(a, b []float64) float64 {
    45  	var x, y, z, w float64
    46  
    47  	for i := 0; i < len(a); i += 4 {
    48  		x += a[i] * b[i]
    49  		y += a[i+1] * b[i+1]
    50  		z += a[i+2] * b[i+2]
    51  		w += a[i+3] * b[i+3]
    52  	}
    53  
    54  	return x + y + z + w
    55  }
    56  
    57  func Dot4(a, b []float64) float64 {
    58  	var sum float64
    59  
    60  	for len(a) >= 4 && len(b) >= 4 {
    61  		s0 := a[0] * b[0]
    62  		s1 := a[1] * b[1]
    63  		s2 := a[2] * b[2]
    64  		s3 := a[3] * b[3]
    65  		sum += s0 + s1 + s2 + s3
    66  		a = a[4:]
    67  		b = b[4:]
    68  	}
    69  	// deal with remainder of a and b
    70  	return sum
    71  }
    72  
    73  func Dot5(a, b []float64) float64 {
    74  	var x, y, z, w float64
    75  
    76  	for len(a) >= 4 && len(b) >= 4 {
    77  		x += a[0] * b[0]
    78  		y += a[1] * b[1]
    79  		z += a[2] * b[2]
    80  		w += a[3] * b[3]
    81  		a, b = a[4:], b[4:]
    82  	}
    83  
    84  	return x + y + z + w
    85  }
    86  
    87  var (
    88  	xs = make([]float64, 10*1024)
    89  	ys = make([]float64, 10*1024)
    90  
    91  	sink float64
    92  )
    93  
    94  func BenchmarkDot1(b *testing.B) {
    95  	for i := 0; i < b.N; i++ {
    96  		sink += Dot1(xs, ys)
    97  	}
    98  }
    99  
   100  func BenchmarkDot2(b *testing.B) {
   101  	for i := 0; i < b.N; i++ {
   102  		sink += Dot2(xs, ys)
   103  	}
   104  }
   105  
   106  func BenchmarkDot3(b *testing.B) {
   107  	for i := 0; i < b.N; i++ {
   108  		sink += Dot3(xs, ys)
   109  	}
   110  }
   111  
   112  func BenchmarkDot4(b *testing.B) {
   113  	for i := 0; i < b.N; i++ {
   114  		sink += Dot4(xs, ys)
   115  	}
   116  }
   117  
   118  func BenchmarkDot5(b *testing.B) {
   119  	for i := 0; i < b.N; i++ {
   120  		sink += Dot5(xs, ys)
   121  	}
   122  }