【问题标题】:For loop performance对于循环性能
【发布时间】:2013-06-29 03:16:13
【问题描述】:

底线:速度很重要。

我查看了我的代码,并决定寻找更多方法来提高它的效率(即使提高一毫秒,那也很棒)。所有这些数据成员、方法、无用的数据创建——我们都被教导要遵循指导方针以及如何去做和不去做。

循环除外。

我们一直被鼓励使用它们,因为它们有助于提高代码的可读性并帮助用户。用户。在我说出了我脑海中的定义之后,我想到了这个想法:

for (int i = 0; i < 100; i++)
{
    //whatever code
}

让我们假设我们知道长度的情况。这将执行代码 100 次,但它执行了 201 次可以省略以帮助机器的操作。如果我们复制粘贴代码 100 次,扔掉初始化、条件和终止会怎么样:

//Code[0]
//Code[1]
//Code[2]
//...

这是一点点,但仍然......

这是效率狂人的常见做法吗?

【问题讨论】:

  • 底线:编译器在这方面比你(或我)更聪明:D。如果您真的对性能感到好奇,请运行一些(嗯,很多)性能配置文件。密切注意可以应用的所有不同编译器优化标志和目标架构。这通常被称为“循环展开”——我敢说这是一个“疯狂”的想法。
  • “疯子”就是这个词。现代编译器和解释器将非常有效地完成这类事情。您应该努力分析您的代码并处理那些耗时且重复执行的部分。我相信你能找到比 for 循环更好的东西
  • 记住,“越大越慢”。

标签: performance for-loop


【解决方案1】:

这是一种称为 loop unrolling 的常见优化,一个好的编译器应该会自动为您完成。根据代码,许多编译器实际上也会展开没有绝对上限的循环。

举个极端的例子,您可能对Duff's device 感兴趣。这允许您在具有可变上限的循环上展开循环,而不必担心最后的“剩余”迭代。

如果您从 0 循环到 200,则将循环展开 200 倍不一定会大大提高您的性能。在生成多少代码和通过避免分支获得多少性能提升之间需要权衡取舍。我认为在很多代码中展开超过 10 个并不常见,但我没有任何引用来支持这个数字。

当今最常见的台式笔记本电脑都运行 x86_64 处理器,这是 superscalar 架构,可以执行诸如乱序执行和分支预测等疯狂的事情。在你的编译器可以做的所有疯狂的事情和你的 CPU 正在做的所有疯狂的事情之间,没有太多需要手动调整这样的小事情。

实际上,您需要小心过度优化。我已经进行了很多实验,其中使用-O3 instead of -O2 进行编译实际上减慢了我的应用程序而不是加速它。我还使用 LLVM 进行了一组实验,在其中测试了相同代码(常见的编译器基准测试)在打开和关闭单个优化时的性能如何变化。对于-O2 集之外的大多数优化,优化带来的伤害和帮助一样多。您确实需要使用您的特定应用程序测试优化,看看它们是有帮助还是有害。

但是,您通常通过选择正确的数据结构和算法来获得最佳性能,而不是像这样的小玩意优化。我发现最好采用以下方法进行优化:

  1. 编写代码,使其可读。
  2. Profile the code 看看哪个部分占用的时间最多。
  3. 看看我是否可以对该部分进行算法/数据结构更改以加快速度。
  4. 当所有其他方法都失败时,请使用这种类型的低级代码转换(您希望编译器会为您处理)。

【讨论】:

    猜你喜欢
    • 2019-02-13
    • 1970-01-01
    • 2014-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-27
    • 2012-06-05
    • 1970-01-01
    相关资源
    最近更新 更多