github.com/fiatjaf/generic-ristretto@v0.0.1/z/simd/baseline.go (about) 1 package simd 2 3 import ( 4 "fmt" 5 "runtime" 6 "sort" 7 "sync" 8 ) 9 10 // Search finds the key using the naive way 11 func Naive(xs []uint64, k uint64) int16 { 12 var i int 13 for i = 0; i < len(xs); i += 2 { 14 x := xs[i] 15 if x >= k { 16 return int16(i / 2) 17 } 18 } 19 return int16(i / 2) 20 } 21 22 func Clever(xs []uint64, k uint64) int16 { 23 if len(xs) < 8 { 24 return Naive(xs, k) 25 } 26 var twos, pk [4]uint64 27 pk[0] = k 28 pk[1] = k 29 pk[2] = k 30 pk[3] = k 31 for i := 0; i < len(xs); i += 8 { 32 twos[0] = xs[i] 33 twos[1] = xs[i+2] 34 twos[2] = xs[i+4] 35 twos[3] = xs[i+6] 36 if twos[0] >= pk[0] { 37 return int16(i / 2) 38 } 39 if twos[1] >= pk[1] { 40 return int16((i + 2) / 2) 41 } 42 if twos[2] >= pk[2] { 43 return int16((i + 4) / 2) 44 } 45 if twos[3] >= pk[3] { 46 return int16((i + 6) / 2) 47 } 48 49 } 50 return int16(len(xs) / 2) 51 } 52 53 func Parallel(xs []uint64, k uint64) int16 { 54 cpus := runtime.NumCPU() 55 if cpus%2 != 0 { 56 panic(fmt.Sprintf("odd number of CPUs %v", cpus)) 57 } 58 sz := len(xs)/cpus + 1 59 var wg sync.WaitGroup 60 retChan := make(chan int16, cpus) 61 for i := 0; i < len(xs); i += sz { 62 end := i + sz 63 if end >= len(xs) { 64 end = len(xs) 65 } 66 chunk := xs[i:end] 67 wg.Add(1) 68 go func(hd int16, xs []uint64, k uint64, wg *sync.WaitGroup, ch chan int16) { 69 for i := 0; i < len(xs); i += 2 { 70 if xs[i] >= k { 71 ch <- (int16(i) + hd) / 2 72 break 73 } 74 } 75 wg.Done() 76 }(int16(i), chunk, k, &wg, retChan) 77 } 78 wg.Wait() 79 close(retChan) 80 var min int16 = (1 << 15) - 1 81 for i := range retChan { 82 if i < min { 83 min = i 84 } 85 } 86 if min == (1<<15)-1 { 87 return int16(len(xs) / 2) 88 } 89 return min 90 } 91 92 func Binary(keys []uint64, key uint64) int16 { 93 return int16(sort.Search(len(keys), func(i int) bool { 94 if i*2 >= len(keys) { 95 return true 96 } 97 return keys[i*2] >= key 98 })) 99 } 100 101 func cmp2_native(twos, pk [2]uint64) int16 { 102 if twos[0] == pk[0] { 103 return 0 104 } 105 if twos[1] == pk[1] { 106 return 1 107 } 108 return 2 109 } 110 111 func cmp4_native(fours, pk [4]uint64) int16 { 112 for i := range fours { 113 if fours[i] >= pk[i] { 114 return int16(i) 115 } 116 } 117 return 4 118 } 119 120 func cmp8_native(a [8]uint64, pk [4]uint64) int16 { 121 for i := range a { 122 if a[i] >= pk[0] { 123 return int16(i) 124 } 125 } 126 return 8 127 }