github.com/weaviate/weaviate@v1.24.6/adapters/repos/db/vector/hnsw/distancer/l2_arm64_test.go (about) 1 // _ _ 2 // __ _____ __ ___ ___ __ _| |_ ___ 3 // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ 4 // \ V V / __/ (_| |\ V /| | (_| | || __/ 5 // \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| 6 // 7 // Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. 8 // 9 // CONTACT: hello@weaviate.io 10 // 11 12 package distancer 13 14 import ( 15 "fmt" 16 "math/rand" 17 "testing" 18 19 "github.com/stretchr/testify/assert" 20 "github.com/weaviate/weaviate/adapters/repos/db/vector/hnsw/distancer/asm" 21 ) 22 23 func L2PureGo(a, b []float32) float32 { 24 var sum float32 25 26 for i := range a { 27 diff := a[i] - b[i] 28 sum += diff * diff 29 } 30 31 return sum 32 } 33 34 func Test_L2_DistanceImplementation(t *testing.T) { 35 lengths := []int{1, 4, 16, 31, 32, 35, 64, 67, 128, 130, 256, 260, 384, 390, 768, 777} 36 37 for _, length := range lengths { 38 t.Run(fmt.Sprintf("with vector l=%d", length), func(t *testing.T) { 39 x := make([]float32, length) 40 y := make([]float32, length) 41 for i := range x { 42 x[i] = rand.Float32() 43 y[i] = rand.Float32() 44 } 45 46 control := L2PureGo(x, y) 47 asmResult := asm.L2(x, y) 48 49 assert.InEpsilon(t, control, asmResult, 0.01) 50 }) 51 } 52 } 53 54 func Test_L2_DistanceImplementation_OneNegativeValue(t *testing.T) { 55 lengths := []int{1, 4, 16, 31, 32, 35, 64, 67, 128, 130, 256, 260, 384, 390, 768, 777} 56 57 for _, length := range lengths { 58 t.Run(fmt.Sprintf("with vector l=%d", length), func(t *testing.T) { 59 x := make([]float32, length) 60 y := make([]float32, length) 61 for i := range x { 62 x[i] = -rand.Float32() 63 y[i] = rand.Float32() 64 } 65 66 control := L2PureGo(x, y) 67 asmResult := asm.L2(x, y) 68 69 assert.InEpsilon(t, control, asmResult, 0.01) 70 }) 71 } 72 } 73 74 func Benchmark_L2_PureGo_VS_Neon(b *testing.B) { 75 r := getRandomSeed() 76 lengths := []int{2, 4, 6, 8, 10, 12, 16, 24, 30, 32, 128, 256, 300, 384, 600, 768, 1024} 77 for _, length := range lengths { 78 b.Run(fmt.Sprintf("vector dim=%d", length), func(b *testing.B) { 79 x := make([]float32, length) 80 y := make([]float32, length) 81 for i := range x { 82 x[i] = -r.Float32() 83 y[i] = r.Float32() 84 } 85 86 b.ResetTimer() 87 88 b.Run("pure go", func(b *testing.B) { 89 for i := 0; i < b.N; i++ { 90 L2PureGo(x, y) 91 } 92 }) 93 94 b.Run("asm Neon", func(b *testing.B) { 95 for i := 0; i < b.N; i++ { 96 asm.L2(x, y) 97 } 98 }) 99 }) 100 } 101 }