在数组中的指定索引之前查找最近的已使用索引(快速)

时间:2009-07-21 07:16:19

标签: c++ optimization memory performance

此问题与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个,我可以使用数组的位图,跳过未使用的对会快得多。

4 个答案:

答案 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,但直到现在我还没有听说过。