【问题标题】:Entropy-Decoder. Extract unknown number of coded coefficients from data熵解码器。从数据中提取未知数量的编码系数
【发布时间】:2012-12-12 12:46:48
【问题描述】:

我需要使用以下算法从流中读取数据:

-从流中计算所有连续的设置位(“1”)。

-然后,从流中再读取 k 个位。 K 是可变的,并且在整个程序中都会发生变化。让我们将读取的数据称为“m”

解码后的数字是

number = (consecutive_set_bits << k) + m;

这个算法被执行了很多次。因此,这段代码尽可能快是至关重要的。

主要问题是 1 字节、2 字节、4 字节等集合中的编码数字的数量是可变的,因此一个简单的实现(我现在脑子里只有一个)需要一个循环从流中读取单个位。在最坏的情况下,我在循环中进行了 14 次迭代,仅针对一个编码系数。

我能以某种方式避免这个循环吗?

【问题讨论】:

    标签: algorithm optimization entropy


    【解决方案1】:

    顺序提取单个位的想法还不错。如果做得好,它可能几乎和任何其他解决方案一样快。

    粒度流中任意位置的位序列g,例如对于(16 位)words 的流,g=16,可以在块上逐块处理大小为 g。

    要从流中提取位置se(带有(e - s) &lt;= g)的位作为“右对齐”数字,示例实现可能是:

    shift = s % g
    
    lowerBits = data[ floor( s / g ) ] >> shift
    upperBits = data[ floor( e / g ) ] << (g - shift)
    
    bitSequence = (lowerBits | upperBits) & ( (1 << (e-s)) -1 )[*]
    

    [*] 最后一项仅掩盖了我们可能得到的任何不需要的高位,并在最终结果中将它们设为0

    (注意数据的字节顺序 :))

    这是否真的会加快速度通常无法确定。 (取决于正在处理的数据、底层计算硬件、使用的编译器等。请注意,需要一些除法和一次模运算,这可能会显着降低算法速度。)

    可以以相同的方式非常有效地逐个提取位。例如:

    blockIndex = floor( bitPosition / g )
    bitIndex = bitPosition % g
    nextBit = (data[ blockIndex ] >> bitIndex) & 1
    

    这当然可以优化以避免blockIndexbitIndexbitPosition 始终仅递增1 时重新计算。

    另一种常见的方法是使用变量“掩码”来提取单个位:

    mask = 1
    index = 0
    while ( not all bits read ) { 
      block = data[index]
      if ( mask & block != 0 ) {
        // a 1 was encountered
      } else {
        // a 0 was encountered
      }
      mask = mask << 1
      if ( mask == 0 ) {
        mask = 1
        index = index + 1
      }
    }
    

    注意mask 如何用于屏蔽当前位并跟踪何时前进到下一个数据块。为此,mask 当然必须与数据块具有相同的宽度g

    总结一下:

    我认为,在一般情况下,该解决方案不会比每次读取一次循环迭代更有效,任何优化只会稍微改变一个方向或另一个方向的性能。

    【讨论】:

    • 你的最后一句话令人失望。我需要让算法运行在 120 毫秒/秒以下。现在大约需要 160 毫秒,其中大约 100 毫秒是因为我通过逐位提取位来计算连续的。我希望会有一个更快的解决方案,但我想不会:P
    • 我假设您已经包含了基本优化? - 尽量避免在循环中重复计算相同的值;就像我在上一个示例中的block = data[index] 操作for each bit - 当然,这应该只在每次index 更改时执行。你能发布你的代码吗?
    • 作为一个信息,我最终使用的最终算法只是读取整个 32 位整数,然后执行 __asm{ 而不是整数; bsr eax,integer } 因此我有连续的,然后再读取 k 位只是移动整数以掩盖你的 k 位。
    • 感谢您回来分享您的解决方案 :) 在这种情况下,您的代码适用于 i386 架构吗?
    • 是的。您可以通过执行 ~integer; 以某种方式使其具有可移植性。并使用 bsr 的内在函数,但在 VS2005 上,由于某种原因,编译器没有为我生成 bsr 指令,所以我不得不在 asm 中执行。当然,这让我陷入 x64 模式,但无论如何。
    猜你喜欢
    • 2018-07-10
    • 2013-01-14
    • 1970-01-01
    • 1970-01-01
    • 2017-09-24
    • 1970-01-01
    • 1970-01-01
    • 2020-01-23
    • 2016-07-07
    相关资源
    最近更新 更多