熵解码器。从数据中提取未知数量的编码系数

时间:2012-12-12 12:46:49

标签: algorithm optimization entropy

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

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

- 然后,从流中读取更多位。 K是可变的,并在整个计划中发生变化。让我们调用读取数据“m”

然后解码的数字是

number = (consecutive_set_bits << k) + m;

该算法执行的次数非常多。因此,这段代码尽可能快地至关重要。

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

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

1 个答案:

答案 0 :(得分:0)

顺序提取单个位的想法并不算太糟糕。如果做得好,它可能几乎与任何其他解决方案一样快。

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

要将位置se(带(e - s) <= 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

(小心数据的结束:))

一般来说,这是否会真正加快速度。 (取决于正在处理的数据,底层计算硬件,使用的编译器和c。请注意,需要一些分区和一个模运算,这可能会显着降低算法速度。)

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

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

这当然可以进行优化,以避免在blockIndex始终仅增加1的情况下重新计算bitIndexbitPosition

另一种常见的方法是使用变量'mask'来提取单个位:

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

总结一下:

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