【问题标题】:Cache locality vs Function Calls缓存局部性与函数调用
【发布时间】:2020-01-20 10:49:36
【问题描述】:

我有一个执行任务的函数,让我们调用这个函数F()。现在,我需要在足够小的时候完成这个任务n。我可以考虑做两件事:

  1. //Code Here... Code-for-function-F() Code-for-function-F() . . . Code-for-function-F() //following code

  2. //Code Here for(int i=0; i<n; ++i) F() //Following code

在第一种情况下,我避免了函数调用开销。但是由于代码重复了 n 次,所以代码可能会相当大,并且会导致更差的缓存位置/性能。对于第二种情况,缓存会更好地利用,但会由于函数调用而导致开销。我想知道是否有人对这两种方法中的哪一种进行了分析。

PS:我知道实际答案可能取决于代码分析告诉我的内容,两者之间是否存在理论上更好的方法?我在 Linux 上使用 c++。

【问题讨论】:

  • 编译器可以自行展开循环。
  • 专注于编写可读的代码,而不是试图超越你的编译器。到目前为止,算法更改通常超过调用或不调用函数对性能的影响。无论如何,如果你想知道,你必须测量。
  • 顺便说一句,我不明白你的推理。 “在第一种情况下,我避免了函数调用开销”两种情况下的函数调用都是相同的,不是吗?
  • @foreknownas_463035818 我的意思是,在第一种情况下,我自己内联函数而不是等待编译器执行它。这样,我最终会复制会导致缓存局部性变差的代码,并且可以避免函数开销。
  • @gundechaHills 这不是代码示例中的内容。无论如何,在决定内联什么和不内联方面,编译器比你更聪明(可能是其他人的 99%)

标签: c++ caching architecture


【解决方案1】:

当问题是哪个代码更快时,没有万能的答案。你必须测量它。

但是,您想到的优化、循环展开和函数内联是编译器真正擅长的技术。在代码中显式应用它们有助于编译器执行更好的优化是很少见的。我宁愿担心通过编写不必要的聪明代码来防止这种编译器优化。

如果你有具体的例子,我建议你看看godbolt。这是一个很好的工具,可以帮助您查看代码变化对编译器输出的影响。

也不要忘记 D.Knuth 的名言:

程序员会浪费大量时间思考或担心 关于,他们程序的非关键部分的速度,以及这些 提高效率的尝试实际上会产生强烈的负面影响 考虑调试和维护。我们应该忘记小 效率,大约 97% 的时间:过早优化是 万恶之根。然而,我们不应该放弃我们在这方面的机会 关键 3%。

它经常被引用不完整,而最后一部分与其余部分一样重要:“但我们不应该放弃那关键的 3% 的机会。”。要知道这 3% 在哪里,您必须分析您的代码。

TL;DR:不要进行过早的优化。首先进行衡量和分析,只有这样您才能知道值得改进的地方以及是否可以得到改进。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-30
    相关资源
    最近更新 更多