github.com/egonelbre/exp@v0.0.0-20240430123955-ed1d3aa93911/vector/compare/axpy_test.go (about)

     1  package compare
     2  
     3  import (
     4  	"slices"
     5  	"strconv"
     6  	"testing"
     7  )
     8  
     9  const N = 10000000
    10  const K = N/5 - 1
    11  
    12  var alpha = float32(1.0)
    13  var xs = makeFloat32(N)
    14  var ys = makeFloat32(N)
    15  
    16  type goAxpyDecl struct {
    17  	name string
    18  	fn   func(alpha float32, xs []float32, incx uintptr, ys []float32, incy uintptr, n uintptr)
    19  }
    20  
    21  type axpyTestCase struct {
    22  	alpha  float32
    23  	n      uintptr
    24  	xs     []float32
    25  	incx   uintptr
    26  	ys     []float32
    27  	incy   uintptr
    28  	expect []float32
    29  }
    30  
    31  func (t axpyTestCase) N() uintptr {
    32  	if t.n == 0 {
    33  		return uintptr(len(t.xs)) / t.incx
    34  	}
    35  	return t.n
    36  }
    37  
    38  var axpyTestCases = []axpyTestCase{
    39  	0: {
    40  		alpha: 1.3,
    41  		xs:    []float32{1}, incx: 1,
    42  		ys: []float32{2}, incy: 1,
    43  		expect: []float32{3.3},
    44  	},
    45  	1: {
    46  		alpha: 1.3,
    47  		xs:    []float32{1}, incx: 1,
    48  		ys: []float32{2}, incy: 1,
    49  		expect: []float32{3.3},
    50  	},
    51  	2: {
    52  		alpha: 1.3,
    53  		xs:    []float32{}, incx: 1,
    54  		ys: []float32{}, incy: 1,
    55  		expect: []float32{},
    56  	},
    57  	3: {
    58  		alpha: 2,
    59  		xs:    []float32{8}, incx: 1,
    60  		ys: []float32{1}, incy: 1,
    61  		expect: []float32{17},
    62  	},
    63  	4: {
    64  		alpha: 3,
    65  		xs:    []float32{1, 2, 3, 4}, incx: 1,
    66  		ys: []float32{1, 1, 1, 1}, incy: 1,
    67  		expect: []float32{4, 7, 10, 13},
    68  	},
    69  	5: {
    70  		alpha: 3,
    71  		xs:    []float32{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, incx: 1,
    72  		ys: []float32{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, incy: 1,
    73  		expect: []float32{4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4},
    74  	},
    75  	6: {
    76  		alpha: 3,
    77  		n:     6,
    78  		xs:    []float32{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, incx: 2,
    79  		ys: []float32{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, incy: 2,
    80  		expect: []float32{4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4},
    81  	},
    82  	7: {
    83  		alpha: 3,
    84  		n:     6,
    85  		xs:    []float32{1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0}, incx: 1,
    86  		ys: []float32{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}, incy: 2,
    87  		expect: []float32{4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4},
    88  	},
    89  	8: {
    90  		alpha: 3,
    91  		n:     6,
    92  		xs:    []float32{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}, incx: 2,
    93  		ys: []float32{1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0}, incy: 1,
    94  		expect: []float32{4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0},
    95  	},
    96  	9: {
    97  		alpha: 3,
    98  		xs:    []float32{1, 2, 3, 5}, incx: 1,
    99  		ys: []float32{-7, -11, -13, -17}, incy: 1,
   100  		expect: []float32{-4, -5, -4, -2},
   101  	},
   102  	10: {
   103  		alpha: 2.3,
   104  		xs:    []float32{-4691.1084, 1844.69, 1986.0142, 3274.4463, 4433.3447}, incx: 1,
   105  		ys: []float32{2613.8955, -355.9663, 898.40283, 2144.5698, 4446.6465}, incy: 1,
   106  		expect: []float32{-8175.6533, 3886.8203, 5466.2354, 9675.796, 14643.339},
   107  	},
   108  	11: {
   109  		alpha: 3,
   110  		xs:    []float32{1, 2, 3, 5, 1, 2, 3, 5}, incx: 1,
   111  		ys: []float32{-7, -11, -13, -17, -7, -11, -13, -17}, incy: 1,
   112  		expect: []float32{-4, -5, -4, -2, -4, -5, -4, -2},
   113  	},
   114  	12: {
   115  		alpha: 3,
   116  		xs:    []float32{0, 1, 2, 3, 5, 1, 2, 3, 5}, incx: 1,
   117  		ys: []float32{0, -7, -11, -13, -17, -7, -11, -13, -17}, incy: 1,
   118  		expect: []float32{0, -4, -5, -4, -2, -4, -5, -4, -2},
   119  	},
   120  }
   121  
   122  var goAxypDecls = []goAxpyDecl{
   123  	{name: "AxpyBasic", fn: AxpyBasic},
   124  	{name: "AxpyUnsafe", fn: AxpyUnsafe},
   125  	{name: "AxpyUnsafeX", fn: AxpyUnsafeX},
   126  	{name: "AxpyUnsafeInline", fn: AxpyUnsafeInline},
   127  	{name: "AxpyPointer", fn: AxpyPointer},
   128  	{name: "AxpyPointerLoop", fn: AxpyPointerLoop},
   129  	{name: "AxpyPointerLoopX", fn: AxpyPointerLoopX},
   130  	{name: "AxpyBasicR4", fn: AxpyBasicR4},
   131  	{name: "AxpyBasicXR4", fn: AxpyBasicXR4},
   132  	{name: "AxpyUnsafeR4", fn: AxpyUnsafeR4},
   133  	{name: "AxpyUnsafeXR4", fn: AxpyUnsafeXR4},
   134  	{name: "AxpyUnsafeR8", fn: AxpyUnsafeR8},
   135  	{name: "AxpyUnsafeXR8", fn: AxpyUnsafeXR8},
   136  	{name: "AxpyUnsafeInlineR4", fn: AxpyUnsafeInlineR4},
   137  	{name: "AxpyUnsafeInlineXR4", fn: AxpyUnsafeInlineXR4},
   138  	{name: "AxpyUnsafeInlineR8", fn: AxpyUnsafeInlineR8},
   139  	{name: "AxpyUnsafeInlineXR8", fn: AxpyUnsafeInlineXR8},
   140  	{name: "AxpyPointerR4", fn: AxpyPointerR4},
   141  	{name: "AxpyPointerLoopR4", fn: AxpyPointerLoopR4},
   142  	{name: "AxpyPointerLoopXR4", fn: AxpyPointerLoopXR4},
   143  	{name: "AxpyPointerLoopInterleaveR4", fn: AxpyPointerLoopInterleaveR4},
   144  	{name: "AxpyPointerLoopInterleaveXR4", fn: AxpyPointerLoopInterleaveXR4},
   145  	{name: "AxpyPointerR4Alt", fn: AxpyPointerR4Alt},
   146  }
   147  
   148  func BenchmarkGo(b *testing.B) {
   149  	for _, axpy := range goAxypDecls {
   150  		b.Run(axpy.name, func(b *testing.B) {
   151  			fn := axpy.fn
   152  			for i := 0; i < b.N; i++ {
   153  				fn(alpha, xs[i&3:], 2, ys, 4, K)
   154  			}
   155  		})
   156  	}
   157  }
   158  
   159  func TestGo(t *testing.T) {
   160  	for _, axpy := range goAxypDecls {
   161  		t.Run(axpy.name, func(t *testing.T) {
   162  			for i, test := range axpyTestCases {
   163  				t.Run(strconv.Itoa(i), func(t *testing.T) {
   164  					lxs := slices.Clone(test.xs)
   165  					lys := slices.Clone(test.ys)
   166  
   167  					axpy.fn(test.alpha, lxs, test.incx, lys, test.incy, test.N())
   168  
   169  					if !equalFloats(lys, test.expect) {
   170  						t.Errorf("wrong result\n\tgot=%v\n\texp=%v\n\tal=%v\n\txs=%v\n\tys=%v", lys, test.expect, test.alpha, test.xs, test.ys)
   171  					}
   172  					if !equalFloats(lxs, test.xs) {
   173  						t.Errorf("xs modified")
   174  					}
   175  				})
   176  			}
   177  		})
   178  	}
   179  }
   180  
   181  func makeFloat32(n int) []float32 {
   182  	r := make([]float32, n)
   183  	for i := range r {
   184  		r[i] = float32(i)
   185  	}
   186  	return r
   187  }