Arrays 是否生锈';s数组边界检查是否会影响性能?

Arrays 是否生锈';s数组边界检查是否会影响性能?,arrays,performance,rust,benchmarking,Arrays,Performance,Rust,Benchmarking,我来自C,我想知道Rust的边界检查是否会影响性能。每次访问可能都需要一些额外的汇编指令,这在处理大量数据时可能会造成伤害 另一方面,处理器性能中代价高昂的部分是内存,因此更多的算术汇编指令可能不会造成影响,但在加载缓存线之后,顺序访问应该非常快,这可能很重要 有人对此进行了基准测试吗?不幸的是,边界检查的成本并不是一个简单的估计。这当然不是“每次检查一个周期”,也不是任何这样容易猜测的成本。这将产生非零影响,但可能微不足道 理论上,通过修改Rust使其失效并运行大规模的生态系统测试,可以测量对

我来自C,我想知道Rust的边界检查是否会影响性能。每次访问可能都需要一些额外的汇编指令,这在处理大量数据时可能会造成伤害

另一方面,处理器性能中代价高昂的部分是内存,因此更多的算术汇编指令可能不会造成影响,但在加载缓存线之后,顺序访问应该非常快,这可能很重要


有人对此进行了基准测试吗?

不幸的是,边界检查的成本并不是一个简单的估计。这当然不是“每次检查一个周期”,也不是任何这样容易猜测的成本。这将产生非零影响,但可能微不足道

理论上,通过修改Rust使其失效并运行大规模的生态系统测试,可以测量对基本类型(如
Vec
)进行边界检查的成本。这将给出某种经验法则,但如果不这样做,很难知道这是接近10%还是十分之一的开销

不过,有一些方法可以比计时和猜测做得更好。这些经验法则主要适用于桌面级硬件;低端硬件或针对不同细分市场的产品将具有不同的特征

如果索引是从容器大小派生的,编译器很有可能完全消除边界检查。在这一点上,发布版本中边界检查的唯一代价是它会间歇性地干扰优化,这可能(但通常不会)妨碍其他优化

如果您的代码分支多、内存访问量大或难以优化,并且要检查的边界很容易访问,边界检查很有可能主要发生在CPU的空闲带宽中,分支预测特别有帮助,在这种情况下,总成本将特别小,尤其是与代码其余部分的成本相比

如果要检查的边界位于几层指针之后,您可能会遇到内存延迟问题,并相应受到影响。然而,CPU中的推测和预测机制将设法掩盖这一点也是合理的;这是非常依赖于上下文的。如果您正在引用内部的数据,而不是在边界检查的同时取消对其的引用,则此风险会放大

如果边界检查处于一个不会使内核饱和的紧密算术循环中,除非妨碍其他编译器优化,否则不太可能直接影响吞吐量。然而,阻碍其他编译器优化可能是任意糟糕的,从没有区别到阻止SIMD并导致因子-10的减速

如果边界检查处于一个严格的算术循环中,会使核心饱和,您将承担上述风险,并且每次边界检查的直接执行惩罚大约为半个周期

如果您的代码足够大,足以使指令缓存紧张,那么您需要担心对代码大小的影响。这通常是适度的,但很难衡量的运行时影响

彼得·科尔德斯在评论中补充了一些进一步的观点。首先,边界检查意味着加载和存储,所以您将运行混合加载,这很可能会在问题/重命名时出现瓶颈。其次,即使并行执行的预测分支也会从预测器获取资源,这可能会导致其他分支的预测更糟

这可能看起来很吓人,事实确实如此。这就是为什么在与您和您的代码相关的级别上度量和理解您的性能非常重要的原因


同样的情况是,自从Rust与边界检查“诞生”以来,它已经产生了降低其成本的方法,例如普及的零成本引用、迭代器(它吸收边界检查,但实际上并不移除边界检查)和一组不同寻常的实用函数。如果你发现自己碰到了一个病态病例,Rust还提供了不安全的逃生舱口。

为什么不自己在你的机器上进行基准测试,这样结果对你来说最准确?一般来说,除非你必须这样做,否则担心低水平的性能影响是毫无意义的。试图预先优化通常会导致复杂的代码,而这些代码并没有真正的性能优势。基准测试不能模拟也不能反映实际使用情况。我可能稍后会对其进行基准测试并自己回答这个问题,但首先我必须学习基础知识(rust中的时间测量是如何工作的?:-D)。我只是认为这可能是有趣的理论,因为我在这个研究中遇到了这个话题,在C语言或C++中的其他语言在HPC。RIST并不总是执行边界检查。我认为对数组进行迭代并不会导致对每个项进行边界检查。如果您需要按索引访问单个项目,则有不安全的函数用于未经检查的访问。@hnefatl:如果您不知道有关某项如何工作的很多详细信息,则无法设计实际测量您想要测量的内容的基准。微基准很容易测量出与作者意图完全不同的东西。“只是基准测试”的回复并不像大多数人想象的那样有用,特别是当我们谈论微基准时。e、 g.你可能会选择一个边界检查没有开销的案例,而忽略了一个事实,即在其他看起来相似或非常不同的案例中也有开销。@PeterCordes是的,我用斜体字评论的最后一部分是关于这一点的“免责声明”,意味着“发明”基准测试通常不会捕获生产代码中出现的情况。“使核心的功能单元饱和”:通常您会在前端遇到瓶颈