【发布时间】:2021-08-22 05:27:14
【问题描述】:
我正在研究一种算法,用于搜索数组以查找给定值的索引。我正在尝试遵循.NET Core CLR 中的类似技术。
我感到困惑的是调用BitOperations.TrailingZeroCount 返回的idx 的值。当我搜索2 时,它应该为我正在搜索的数据返回一个索引值1。我得到的是4。我是否需要将字节偏移量转换回实际类型?这是写这个最有效的方法吗?关于在 .NET 中使用内部函数的文档并不多。
open System
open System.Runtime.Intrinsics.X86
open System.Runtime.Intrinsics
open System.Numerics
#nowarn "9"
#nowarn "20"
[<EntryPoint>]
let main argv =
let searchSpace : Span<int32> = Span [| 1 .. 8 |]
let pSearchSpace = && (searchSpace.GetPinnableReference ())
let search = Sse2.LoadVector128 (pSearchSpace)
let value = 2
let values = Vector128.Create value
let comparison = Sse2.CompareEqual (values, search)
let matches = Sse2.MoveMask (comparison.AsByte())
if matches > 0 then
let idx = BitOperations.TrailingZeroCount matches
printfn "%A" idx // <--- This prints 4 instead of 1
0 // return an integer exit code
【问题讨论】:
-
顺便说一句,如果您使用的是 256 位向量,您可能需要
if matches != 0。vpmovmskb会给你一个 32 位的位掩码,所以可以设置符号位。此外,如果您正在线性搜索大于 1 个向量的数组,并且预计第一个匹配不会立即出现,您可能希望将一些比较结果组合在一起,例如 glibc memchr 的做法 (code.woboq.org/userspace/glibc/sysdeps/x86_64/multiarch/…),然后整理出来当您知道 2 或 4 个向量(1 或 2 个缓存行)中存在一个时,匹配的位置。 -
这正是我所期待的。我一直在研究 SIMD 以快速搜索 int 数组以找到特定值的索引。在我的情况下,数组已排序并且值是唯一的。数组的大小可能在 1K - 10K 元素的范围内。
-
数组已排序?所以你在二进制搜索让你接近之后使用它?或者您正在使用隐式 quint-tree 或带有 SIMD 的东西来决定接下来要下降 5 个子树中的哪一个...What is the most efficient way to implement a BST in such a way the find(value) function is optimized for random values in the tree on x86? SIMD 对 1k 元素的线性搜索甚至可能不如普通的二进制搜索好。 (如果您希望数据在缓存中很热,请使其无分支。)
-
问题的完整描述是我有两个数组,A和B。两者都是唯一int的排序数组。对于 A 中的每个元素,我需要在 B 中找到匹配项的索引。由于它们是排序的,我想利用我只需要为 A 中的每个剩余元素搜索 B 中的剩余值。我一直查看 SIMD 以同时执行许多比较。
-
我明白了。也许蛮力
pcmpgtd搜索,直到找到更大的,然后pcmpeqd看看最后一个向量中是否有匹配项。然后你不会一直走到最后,如果元素存在的话,你就不会走到最后。