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 }