LatencyFlex:减少游戏延迟的新方法

2022-01-10 22:39:05

这篇文章描述了LatencyFlex的内部工作,这是一组图书馆,实现了视频游戏的延迟减少,作为NVIDIA反射的供应商替代替代品。

一段时间后,我遇到了谷歌的精彩拥堵控制算法,BBR。 BBR旨在解决网络中的长期问题:BufferBloat。 BufferBloop的原因是之前,拥塞控制依赖于数据包丢失,这是缓冲区已满的信号。因此,这些算法最终可能会在最坏情况下运行。但事实证明,拥有挤塞的另一个信号,可以在达到满带宽时立即使用,并且它被称为延迟。 BBR利用此度量来实现最佳操作点的拥塞控制。

在这篇文章中,我将通过将BBR的行为分解为两部分,然后描述如何在LatencyFlex中使用这些想法。

为了测量MAX带宽,BBR周期性地进入“探测带宽”模式:它暂时增加了分组发送速率,从而创建队列并允许我们看出更多带宽是否可用。然后,它将发送速率降低相同的量,以保持平均发送速率相同,并删除在临时发送速率凹凸期间可能创建的任何排队。该行为是由BBR纸中的下图描述的:

在LatencyFlex中,我们基本上使用了同样的想法,但在更高的频率下:我们在“探测帧速率”模式下运行一帧,然后使用下一个帧漏任何队列,然后重复。至关重要的差异是我们使用不同的估计器进行吞吐量和延迟。在BBR中,通过$$ \ widehat {\ text {btlbw}} = \ max(\ text {deliveryrate})测量带宽。$$这适用于bbr,因为$ \ text {forluserrate} $在长窗口中平滑方差足够低。但是,在LatencyFlex中,我们需要从最新的帧时间值派生实时帧速率,这是非常嘈杂的。使用最大值会使估算器强烈偏见。相反,我们使用指数加权的移动平均值,这给出了一个无偏估计:

我们还将负增益应用于BBR中。在LatencyFlex中,我们使用-1.5%,被确定为良好的测试平衡。

我们在上一节中讨论的步行者有一个问题:适应带宽减少需要很长时间。这是因为有两个原因:

overpacing创建队列(以比例比例在极限上的比例),并且步行者只能以等于我们指定的余量的速率排出队列(BBR的1%,LFX为1.5%)。前者可以比后者快得多,这意味着它会恢复到最佳操作会过度长时间。

这给出了一个“BrickWall”,它可以防止延迟无限期地增加,如下面的BBR纸上所示:

对于每个帧,我们预测它将完成的时间。这是通过将估计的延迟添加到开始时间来派生这一点。

预测和实际完成之间的差异等于延迟估计和真实地之间的差异。该算法所做的是保持延迟常数:如果延迟由于排队而增加,则尝试将队列减少相同的数量。延迟将暂时飙升,直到我们可以做出反应,但很快就会恢复到所需的低值。

本说明省略了许多我在实际实现中做出的复杂决策以实现稳定性,以避免将帖子变得太长。我在代码中记录了它们,尽管一些稳定性属性仍然不太了解。

LatencyFlex的有意识的设计决策是它将整个管道视为黑匣子,只假设瓶颈的排队将反映在延迟中。这是一个非常强大的模型,适应各种瓶颈,不限于GPU。

另一方面,NVIDIA反射依赖于游戏引擎代码的显式仪器。它具有用于仿真,渲染和呈现线程的执行标记,用于识别线程之间的通信,以及启用此类优化的选项BusemAstoOptimize。看起来它有一个没有这些标记的模式,但据我所知,所有公布的游戏似乎都使用显式标记。

LatencyFlex可用于Linux用户,可以注入支持NVIDIA反射的游戏,也可以与某些不支持反射的游戏一起使用,但满足某些游戏发动机条件。如果您有兴趣,请尝试一下。未来,我期待开发游戏开发人员的一体化,一旦我有信心,LFX就足够稳定为最终产品。