此问题与Array of pairs of 3 bit elements
有关
这个数组有52对(大约40个字节),我想在指定的一个之前找到第一对,它的值与0不同(使用对)。
显而易见的解决方案是检查每一对<比这个(从右到左扫描),但如果有许多未使用的对(设置为0),这似乎是非常低效的。
这张图片可以更好地解释这种情况:
使用对0,1和51
我想在51之前找到第一个使用的对(这里是1)。
我试过像
这样的技巧if(*((int *)&array[arrayPos]) == 0) {
arrayPos -= sizeof(int);
pairPos -= ???
}
这里的问题是从 pairPos 中减去并不那么简单,因为6位/对,所以我以查找表为基础,基于 pairPos 和 arrayPos ,所有这些使得解决方案的表现就像平凡的一样。
有没有办法让这个查找更快?另一个问题是只有一个未使用的字节...也许我可以为另一个字节留出空间4.如果至少有7个,我可以使用数组的位图,跳过未使用的对会快得多。
答案 0 :(得分:1)
你能说出代表空对的相邻字节值吗?
我想建议查看字节而不是位。
任何给定的字节,如果它是一对空的6位字符的左手贡献者必须适合特定的位掩码,其值取决于他的位置。 ?? ?? 00 00或?? 00 00 00或其他什么。您可以依次将每个字节视为最左边的字节。一个简单的查找表,可以使用哪个掩码。
因此我们实际上不必在考虑它们之前拔出6位字符。
我们可以做得更好,丢弃一个字节作为候选人,我们现在可以跳过左边的一个吗?
如果我们的掩码是00 00 00 00,那么如果失败那么我们的邻居就在左边,如果第一位被设置,则是,是的。
这实际上会让事情变得更快吗?
答案 1 :(得分:1)
处理组中的6位值。
您可以在32位字中使用5个值的组,这会浪费2位或大约7%的空间。如果一个单词中的所有值都是0,则该单词为零,因此找到非空单词很快,然后检查单词中的5个值。
如果你不能忍受一点浪费的空间,请使用96位组,其中96是6和32的最小公倍数。将16位6位的值打包成3个32位字。
答案 2 :(得分:0)
我找到的最佳解决方案是:
1.使项目1字节(不是之前的6位) - 谢谢Skizz
2.使用位图查看左侧最近的项目。这比回到djna所描述的技术要快得多。
速度提升令人印象深刻:
在一个测试案例中,从13s开始,它现在是6.5s
在另一个,从7.4s到3.6s
表现加倍:D
再次感谢您的回答!
答案 3 :(得分:-1)
有用于搜索位阵列的处理器特定指令。这些可以作为编译器内部函数提供。许多Linux文件系统都广泛使用它们。
__ builtin_ffs()是GCC中的一个。
ffsll()可能是POSIX,但直到现在我还没有听说过。