简体   繁体   English

寻找更有效的位域解码算法

[英]Looking for a more efficient bitfield decode algorithm

I have a Visual Studio 2008 C++ application where I receive a bit map (not an image). 我有一个Visual Studio 2008 C ++应用程序,我收到一个位图(不是图像)。 Each bit that is flipped corresponds to a position on a decode map. 翻转的每个位对应于解码图上的位置。

typedef unsigned char BYTE;
const unsigned int COL_COUNT = 8;
const unsigned int ROW_COUNT = 4;

static char g_decode_map[ ROW_COUNT ][ COL_COUNT ] = 
{
    { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' },
    { 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p' },
    { 'q', 'r', 's', 't', 'u', 'v', 'w', 'x' },
    { 'y', 'z', ',', '.', ' ', ':', '-', '+' }
};

// current implementation
void Decode( const BYTE bitmap[ ROW_COUNT ], 
             const char decode_map[ ROW_COUNT ][ COL_COUNT ], 
             char decoded[ ROW_COUNT * COL_COUNT ] )
{
    int found = 0;
    for( int i = 0; i < ROW_COUNT; ++i )
    {
        for( int j = 0; j < COL_COUNT; ++j )
        {
            if( std::bitset< COL_COUNT >( bitmap[ i ] ).test( j ) )
            {
                decoded[ found++ ] = g_decode_map[ i ][ COL_COUNT - j - 1 ];
            }
        }
    }
}

int main( int argc, char* argv[] )
{
    BYTE bitmap[ ROW_COUNT ] = { 0x01, 0x80, 0x00, 0x00 };
    // expected output { 'h', 'i' } or { 'i', 'h' } order is unimportant

    char decoded[ ROW_COUNT * COL_COUNT + 1 ] = { };
    Decode( bitmap, g_decode_map, decoded );
    printf( "Decoded: %s\r\n", decoded );
    return 0;
}

My current decode implementation works fine, but it strikes me that there may be a more efficient way of doing this. 我当前的解码实现工作正常,但我觉得可能有一种更有效的方法。 Can anybody suggest a more performant algorithm? 任何人都可以建议一个更高性能的算法吗?

It would be faster to test whether or not each bit is set with bitwise operations as opposed to creating a bitset for each bit that is tested. 测试每个位是否通过按位运算设置会更快,而不是为每个被测试的位创建位集。 Try something like this: 尝试这样的事情:

for( int i = 0; i < ROW_COUNT; ++i ) {
    for( int j = 0; j < COL_COUNT; ++j ) {
        if(bitmap[i] & (1 << j)) {
            ...

1 << j produces a mask that only has the bit you are wanting to test set. 1 << j生成一个只有你想要测试的位的掩码。 Bitwise anding the mask with your bitmap byte returns true only if that bit is set in bitmap[i] . 只有在bitmap[i]设置该bitmap[i]时,使用位图字节对掩码进行按位和返回才会返回true。 The result of this conditional should be equivalent to the result of your conditional, and it should be a lot faster. 这个条件的结果应该等同于条件的结果,它应该快得多。

You're doing 64 conditional checks. 你正在进行64次条件检查。 32 in the for loops, and 32 inside the for loop. for循环中为32,for循环中为32。 If you cannot get rid of the 32 inside the for loop, the best you can do is loop unrolling to reduce the number of conditional statements being executed by the forloops. 如果你无法摆脱for循环中的32,你可以做的最好是循环展开以减少forloops正在执行的条件语句的数量。 With the row and column length being defined as constants. 将行和列长度定义为常量。 You can unroll the loops and hardcode some of the numbers for the indices. 您可以展开循环并对索引的一些数字进行硬编码。 Instead of having the inner for loop, you could write 8 if statements like below. 您可以编写8个if语句,而不是内部for循环。

This leave the question, what if someone changes the constant values? 这就留下了一个问题,如果有人改变常数值怎么办? Then the code breaks. 然后代码中断了。 That is correct. 那是对的。 If you need it to be robust enough to withstand that, you can use compile time recursion to unroll the loops(links below). 如果你需要它足够强大以抵御它,你可以使用编译时递归来展开循环(下面的链接)。 Also, anyone who looks at your code will cower in fear and think you're a god. 此外,任何看过你的代码的人都会在恐惧中畏缩,并认为你是一个上帝。 :P Also, Jason's solution would speed things up a bit too. :P另外,杰森的解决方案也会加快速度。

if( std::bitset< COL_COUNT >( bitmap[ i ] ).test( 0 ) )  
if( std::bitset< COL_COUNT >( bitmap[ i ] ).test( 1 ) )  
if( std::bitset< COL_COUNT >( bitmap[ i ] ).test( 2 ) )  
if( std::bitset< COL_COUNT >( bitmap[ i ] ).test( 3 ) )  
...
if( std::bitset< COL_COUNT >( bitmap[ i ] ).test( 7 ) )

Compile Time Loops(Answer #1) 编译时间循环(答案#1)
Template Meta Programming 模板元编程

This is how to do it fast, assuming COL_COUNT == 8 (to do it really fast, use the in-line assembler): 这是如何快速完成的,假设COL_COUNT == 8 (要做得非常快,请使用COL_COUNT == 8汇编程序):

for( int i = 0; i < ROW_COUNT; ++i )
    {
        unsigned char next_byte = bitmap[i] ;
        for( int j = 0; j < COL_COUNT; ++j )
        {
            if (next_byte & 0x80)
            {
                decoded[ found++ ] = g_decode_map[ i ][ j ];
            }
            next_byte <<= 1 ;
        }
    }

I have coded it to reproduce the behaviour of your program -- but are you sure you have it right? 我已将其编码为重现您程序的行为 - 但您确定自己拥有它吗? I would expect you to increment found every time, not just when a 1 -bit is found. 我希望你递增found每一次,不只是当一个1位被发现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM