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



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

-对流中所有连续的设置位("1"s)进行计数。

-然后,从流中再读取k个比特。K是可变的,在整个程序中都会发生变化。让我们调用读取数据"m">

解码后的数字就是

number = (consecutive_set_bits << k) + m;

这个算法执行的次数非常多。正因为如此,这段代码尽可能快是至关重要的。

主要问题是,1字节、2字节、4字节等集合中的编码数是可变的,因此一个微不足道的实现(我现在脑子里唯一的实现)需要一个从流中读取单个比特的循环。在最坏的情况下,对于一个编码系数,我在循环中有14次迭代。

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

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

粒度g的流中任意位置的比特序列,例如,对于(16比特)words的流,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

(小心数据的尾数:)

这是否真的会加速事情的发展还不能确定。(这取决于正在处理的数据、底层计算硬件、使用的编译器。注意,需要一些除法和一个模运算,这可能会显著减慢算法的速度。)

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

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

如果并且当bitPosition总是仅递增1时,这当然可以被优化以避免blockIndexbitIndex的重新计算。

另一种常见的方法是使用变量"掩码"来提取单个比特:

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

综上所述:

我认为,在一般情况下,该解决方案不会比每读取一位一次循环迭代更高效,任何优化都只会在某个方向上略微改变性能。

最新更新