【发布时间】:2009-01-06 21:34:12
【问题描述】:
我正在逐字节地遍历二进制数据的内存块。
目前我正在做这样的事情:
for (i = 0; i < data->Count; i++)
{
byte = &data->Data[i];
((*byte & Masks[0]) == Masks[0]) ? Stats.FreqOf1++; // syntax incorrect but you get the point.
((*byte & Masks[1]) == Masks[1]) ? Stats.FreqOf1++;
((*byte & Masks[2]) == Masks[2]) ? Stats.FreqOf1++;
((*byte & Masks[3]) == Masks[3]) ? Stats.FreqOf1++;
((*byte & Masks[4]) == Masks[4]) ? Stats.FreqOf1++;
((*byte & Masks[5]) == Masks[5]) ? Stats.FreqOf1++;
((*byte & Masks[6]) == Masks[6]) ? Stats.FreqOf1++;
((*byte & Masks[7]) == Masks[7]) ? Stats.FreqOf1++;
}
面具在哪里:
for (i = 0; i < 8; i++)
{
Masks[i] = 1 << i;
}
(不知何故,我在循环或内联函数中没能做到这么快,所以我把它写出来了。)
有人对如何改进第一个循环有任何建议吗?我对深入浅出相当缺乏经验。
这似乎是一件愚蠢的事情。但我正在实施压缩算法。我只想让位访问部分正确。
谢谢!
PS:这是在 Visual Studio 2008 编译器中。因此,如果建议适用于该编译器,那就太好了。
PPS:我刚刚意识到,我不需要增加两个计数。一个就足够了。然后计算最后的总位数的差异。 但这将特定于仅计数。我真正想要快速完成的是位提取。
编辑: 提出的查找表想法很好。 我意识到我在标题中提出了错误的问题。 因为最终我要做的不是计算位,而是尽可能快地访问每个位。
另一个编辑: 是否可以在数据中仅将指针前移一位?
另一个编辑: 感谢您迄今为止的所有回答。
我想在接下来的步骤中实现一个不分析上下文的简单二进制算术编码器。所以我现在只对单个位感兴趣。最终它将成为一个上下文自适应 BAC,但我会留到以后。
可以选择处理 4 个字节而不是 1 个字节。但是超过 32 位的循环也很昂贵,不是吗?
【问题讨论】:
-
查看以下链接了解十几个与位相关的内容:Bit Twiddling Hacks
-
不,您不能将指针前移一位。
-
我认为您不想将指针前移一位。您希望对 CPU 的字长进行操作,以使事情尽可能地运行。获得 8 位所需的滴答数与 32 位相同......
-
@Paul - 你可以,但它会修改底层数据......好吧,我想它不会真正推进指针,只是将数据移动到指向下一位的指针......无论如何,仍然不推荐......
-
你能说一下你想对每个位做什么(在访问它们之后)吗?一些上下文可能会有所帮助。
标签: c performance optimization bitmask