【问题标题】:Simplified algorithm for calculating remaining space in a circular buffer?用于计算循环缓冲区中剩余空间的简化算法?
【发布时间】:2010-10-01 19:54:56
【问题描述】:

我想知道是否有比这更简单(单一)的方法来计算循环缓冲区中的剩余空间?

int remaining = (end > start)
                ? end-start
                : bufferSize - start + end;

【问题讨论】:

  • 这对我来说看起来不错。唯一的其他选择是,如果这是在一个类中,那么将剩余空间保留在一个变量中。

标签: c++ circular-buffer


【解决方案1】:

我知道的旧线程,但认为这可能会有所帮助。

不确定这在 C++ 中实现的速度有多快,但在 rtl 中,如果大小为 n^2,我们会这样做

remaining = (end[n] ^ start[n])
            ? start[n-1:0] - end[n-1:0]
            : end[n-1:0] - start[n-1:0];

remaining = if (end[n] ^ start[n]) {
              start[n-1:0] - end[n-1:0]
            } else { 
              end[n-1:0] - start[n-1:0] 
            };

【讨论】:

    【解决方案2】:

    如果您的循环缓冲区大小是 2 的幂,您可以通过使用 startend 表示虚拟流中的位置而不是循环缓冲区存储的索引来做得更好。假设startend 是无符号的,上面变成:

    int remaining= bufferSize - (end - start);
    

    实际上从缓冲区中取出元素有点复杂,但是开销通常足够小,具有 2 大小的循环缓冲区的幂(只是用 bufferSize - 1 屏蔽)以使循环缓冲区的所有其他逻辑变得更多更简单,更清洁。另外,您可以使用所有元素,因为您不再担心end==start

    【讨论】:

      【解决方案3】:

      嗯……

      int remaining = (end - start + bufferSize) % bufferSize;
      

      13 个代币,我赢了吗?

      【讨论】:

      • 这很简短,尽管在大多数架构上添加分隔符会使您的版本变慢。
      • 所以将缓冲区大小设为 2 的幂。
      • 12 年,没有人提到这个计算是 size 不是 remaining :) +2 个令牌来修复
      【解决方案4】:

      失去条件:

      int remaining = (end + bufferSize - start - 1) % bufferSize + 1
      

      编辑:-1+1 适用于 end == start 时的情况。在这种情况下,此方法将假定缓冲区为空。根据缓冲区的具体实现,您可能需要调整这些以避免出现偏离 1 的情况。

      【讨论】:

      • 在 C 和 C++ 中,% 不是真正的模运算符,而是余数。不同之处在于,当其中一个操作数为负数时,结果的符号是实现定义的。
      • 不是buffersize + 1需要在括号之间吗?
      • 添加 abs() 调用也会减慢速度
      【解决方案5】:

      根据 C++ 标准,第 5.6 节,第 4 段:

      二元 / 运算符产生商,二元 % 运算符产生第一个表达式除以第二个表达式的余数。如果 / 或 % 的第二个操作数为零,则行为未定义;否则 (a/b)*b + a%b 等于 a。如果两个操作数都是非负数,则余数是非负数;如果不是,则余数的符号是​​实现定义的。

      脚注表明最好将商向零舍入,这会使余数为负数。

      因此,(end - start) % bufferSize 方法不能可靠地工作。 C++ 没有模运算(无符号整数类型提供的意义除外)。

      j_random_hacker 推荐的方法不同,看起来不错,但我不知道它在简单性或速度方面有什么实际改进。 boolean 到 int 的转换很巧妙,但需要心理解析,而且这种修改可能比使用 ?: 更昂贵,具体取决于编译器和机器。

      我认为你已经有了最简单和最好的版本,我不会改变它。

      【讨论】:

      • 同意 -- 代码清晰度高于任何一天 0.001% 的速度提升! :)
      【解决方案6】:

      如果您担心预测不佳的条件会减慢 CPU 的流水线速度,可以使用以下方法:

      int remaining = (end - start) + (-((int) (end <= start)) & bufferSize);
      

      但这可能是过早的优化(除非您确实将其确定为热点)。坚持使用您当前的技术,这更具可读性。

      【讨论】:

        猜你喜欢
        • 2012-01-03
        • 2011-10-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多