计算循环缓冲区中剩余空间的简化算法?

发布于 2024-07-12 03:22:01 字数 172 浏览 6 评论 0原文

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

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

I was wonder if there is a simpler (single) way to calculate the remaining space in a circular buffer than this?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

番薯 2024-07-19 03:22:01

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

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

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

If you're worried about poorly-predicted conditionals slowing down your CPU's pipeline, you could use this:

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

But that's likely to be premature optimisation (unless you have really identified this as a hotspot). Stick with your current technique, which is much more readable.

断肠人 2024-07-19 03:22:01

嗯...

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

13 个代币,我赢了吗?

Hmmm....

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

13 tokens, do I win?

梦冥 2024-07-19 03:22:01

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

int remaining= bufferSize - (end - start);

实际上从缓冲区中获取元素要复杂一些,但开销通常足够小,其幂次方为2 大小的循环缓冲区(仅使用 bufferSize - 1 进行屏蔽),使循环缓冲区的所有其他逻辑更加简单和清晰。 另外,您可以使用所有元素,因为您不再担心 end==start

If your circular buffer size is a power of two, you can do even better by having start and end represent positions in a virtual stream instead of indices into the circular buffer's storage. Assuming that start and end are unsigned, the above becomes:

int remaining= bufferSize - (end - start);

Actually getting elements out of the buffer is a little more complicated, but the overhead is usually small enough with a power of 2 sized circular buffer (just masking with bufferSize - 1) to make all the other logic of your circular buffer much simpler and cleaner. Plus, you get to use all the elements since you no longer worry about end==start!

情绪少女 2024-07-19 03:22:01

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

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

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

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

j_random_hacker 推荐的方法是不同的,看起来不错,但我不知道它在简单性或速度方面有任何实际的改进。 将布尔值转换为 int 是巧妙的,但需要心理解析,并且根据编译器和机器的不同,这种调整可能比使用 ?: 更昂贵。

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

According to the C++ Standard, section 5.6, paragraph 4:

The binary / operator yields the quotient, and the binary % operator yields the remainder from the division of the first expression by the second. If the second operand of / or % is zero the behavior is undefined; otherwise (a/b)*b + a%b is equal to a. If both operands are nonnegative then the remainder is nonnegative; if not, the sign of the remainder is implementation-defined.

A footnote suggests that rounding the quotient towards zero is preferred, which would leave the remainder negative.

Therefore, the (end - start) % bufferSize approaches do not work reliably. C++ does not have modular arithmetic (except in the sense offered by unsigned integral types).

The approach recommended by j_random_hacker is different, and looks good, but I don't know that it's any actual improvement in simplicity or speed. The conversion of a boolean to an int is ingenious, but requires mental parsing, and that fiddling could be more expensive than the use of ?:, depending on compiler and machine.

I think you've got the simplest and best version right there, and I wouldn't change it.

云朵有点甜 2024-07-19 03:22:01

失去条件:

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

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

Lose the conditional:

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

Edit: The -1 and +1 are for the case when end == start. In that case, this method will assume the buffer is empty. Depending on the specific implementation of your buffer, you may need to adjust these to avoid an off-by-1 situation.

度的依靠╰つ 2024-07-19 03:22:01

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

不确定这在 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] 
            };

Older thread I know but thought this might be helpful.

Not sure how fast this implements in C++ but in rtl we do this if size is n^2

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

or

remaining = if (end[n] ^ start[n]) {
              start[n-1:0] - end[n-1:0]
            } else { 
              end[n-1:0] - start[n-1:0] 
            };
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文