baseline.go 2.2 KB

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