【问题标题】:Finding the nearest used index before a specified index in an array (Fast)在数组中的指定索引之前查找最近使用的索引(快速)
【发布时间】:2010-11-12 13:30:22
【问题描述】:

这个问题与Array of pairs of 3 bit elements有关
这个数组有 52 对(大约 40 个字节),我想在指定的数组之前找到第一对,它的值不同于 0(使用的对)。 显而易见的解决方案是检查每一对

这张图片可以更好地解释这种情况:

使用了第 0、1 和 51 对。
我想在 51 之前找到第一个使用的对(这里是 1)。

我尝试了类似的技巧

if(*((int *)&array[arrayPos]) == 0) {
    arrayPos -= sizeof(int);
    pairPos -= ???
}  

这里的问题是,从pairPos中减去并不是那么简单,因为6位/对,所以我以一个基于pairPos之间的一些关系的查找表结束> 和 arrayPos,所有这一切都使解决方案的性能变得微不足道。

有什么方法可以让这个查找更快?另一个问题是只有 1 个未使用的字节......也许我可以为另外 4 个腾出空间。如果至少有 7 个,我可以使用数组的位图,跳过未使用的对会更快。

【问题讨论】:

  • 数据的格式一定要这样吗。有时您可以通过更改数据的布局来提高算法的效率。

标签: c++ optimization memory performance


【解决方案1】:

我找到的最佳解决方案是:
1. 将项目设为 1 个字节(而不是以前的 6 位)-感谢 Skizz
2. 使用位图查看左边最近的项目。这比使用 djna 描述的技术返回要快得多。

速度提升令人印象深刻:
在一个测试用例中,从 13 秒到现在 6.5 秒
在另一个,从 7.4s 到 3.6s
性能翻了一番 :D

再次感谢您的回答!

【讨论】:

    【解决方案2】:

    分组处理 6 位值。

    您可以在 32 位字中使用 5 个值的组,这会浪费 2 位或大约 7% 的空间。如果一个单词中的所有值都为 0,那么该单词为零,因此可以快速找到一个非空单词,然后检查该单词中的 5 个值。

    如果您不能忍受一点浪费的空间,请使用 96 位组,其中 96 是 6 和 32 的最小公倍数。即将 16 个 6 位的值打包成三个 32 位字。

    【讨论】:

    • 现在我买得起了,我弥补了一些空间。但我首先尝试使用位图的方法。
    【解决方案3】:

    你能说一下代表空对的相邻字节值吗?

    我想建议查看字节而不是位。

    任何给定的字节如果要成为一对空的 6 位字符的左手贡献者,则必须适合特定的位掩码,其值取决于他的位置。 ?? ?? 00 00 或 ?? 00 00 00 或其他。您可以依次将每个字节视为最左边的字节。可以使用一个简单的查找表来查找要使用的掩码。

    因此我们实际上不必在考虑它们之前提取 6 位字符。

    我们可以做得更好吗,丢弃了一个字节作为候选,我们现在可以跳过左边的那个吗?

    在我们的掩码为 00 00 00 00 的情况下,如果失败,那么我们左边的邻居,如果第一个位被设置,是的。

    这真的会让事情变得更快吗?

    【讨论】:

    • 我无法使对 1 字节,没有足够的空间 :( 我尝试了这种方法,但它并没有更快,因为我需要保持数组中的位置和同步对。有时当我返回数组中的 4 个字节时,该对返回 3 个位置,有时返回 4 个位置。这取决于数组位置中的对之间的某些关系:(
    • 这不是我的建议。我将编辑建议以进一步解释。
    • 我现在明白了 :) 但我设法腾出一些空间,现在可以放置数组的位图。可能我会使用 bsr/bsl 来找到第一个使用的对。如果这不能加快速度,我会试试你说的。
    【解决方案4】:

    有用于搜索位数组的处理器特定指令。这些可以作为编译器内在函数提供。许多 Linux 文件系统广泛使用这些。

    __builtin_ffs() 是 GCC 中的一个。

    ffsll() 可能是 POSIX,虽然我直到现在才听说过。

    【讨论】:

    • 如果我有足够的空间来制作数组的位图(1 表示使用对),这将很有用。但是为此至少需要 7 个字节(52/8),这太多了:(
    猜你喜欢
    • 1970-01-01
    • 2018-06-05
    • 2011-08-29
    • 2017-03-15
    • 2012-10-25
    • 1970-01-01
    • 1970-01-01
    • 2013-07-22
    • 1970-01-01
    相关资源
    最近更新 更多