繁体   English   中英

比特流优化

[英]Bitstream Optimizations

我有一个程序,可以从比特流中读取大量数据。 我执行此操作的方法效率不高,因为在进行性能测试时,大部分时间都花在了read功能上。 这是我的阅读功能:

uint32_t bitstream::read(bitstream::size_type n) {
    uint32_t a = data[pos / 32];
    uint32_t b = data[(pos + n - 1) / 32];
    uint32_t shift = pos & 31;

    a >>= shift;
    b <<= 32 - shift;
    uint32_t mask = (uint32_t)(((uint64_t)1 << n) - 1);
    uint32_t ret = (a | b) & mask;

    pos += n;
    return ret;
}

我该如何进一步优化? 我的分析器说,此功能的大部分时间都花在计算ret上。

编辑:

关于内部,这是我设置数据的方式:

bitstream::bitstream(const std::string &dat) : size( dat.size()*8 ) {
    // data has the type std::vector<uint32_t>
    data.resize((dat.size() + 3) / 4 + 1);
    memcpy(&data[0], dat.c_str(), dat.size());
}

您是否总是读取相同数量的位数,还是有所不同?

如果是这样,则可以尝试编写一个只读取那么多位的函数: n为常数可以使编译器进行一些更积极的优化。 (如果n始终为1,那么您可以编写一个更简单的读取方法)

答案主要取决于您使用的CPU体系结构和编译器,而不取决于语言。 如果您的CPU <32位或在右移方面做得不好,并且/或者幼稚地实现了编译器的移位子例程,那么您通常会不走运。 您可能会牺牲大量程序内存并显式地编写所有情况(即switch()-结合pos模32与n的组合),或者您可以尝试通过将移位与uint16_t和uint8_t短路来完成编译器的工作工会。

您可以在代码中以非常便宜的方式执行的操作是使用预计算的类const数组作为掩码,而不是每次在函数中对其进行计算。

您可以尝试在uint64_t中保留64位的缓冲区,并在其降至32位以下时立即读取另一个32位的字。 如果您经常读取小于32位的大小,这可能会有所帮助。

如果pos可以是0,然后shift也可以是0。结果b被左移32位,它有效地设置为0,并且右移位a由0无任何效果为好。 在这种情况下,应尽早终止操作,以避免无意义的操作。

此外,您可以尝试使用掩码表来消除一个移位操作,为此您只需要32个条目的uint32_t数组。

大多数现代的Intel CPU具有两个ALU单元,要求它们连续执行三个shfit,然后通过使用更多的ALU操作来计算取决于这些移位结果的结果,这将限制您的吞吐量。

最后,如果代码将在具有BMI功能的CPU上执行,则可以使用BEXTR指令或内在函数从位置start处的src提取len位。

有关位操作指令的更多信息,请参见http://en.wikipedia.org/wiki/Bit_Manipulation_Instruction_Sets

暂无
暂无

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

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