我应该避免循环中常量之间的操作吗?

时间:2018-04-23 00:31:13

标签: c++ performance caching optimization constants

我想知道在c ++中是否存在某种优化或缓存,以防止常量之间的相同数学运算被重复,尤其是在循环中,从而降低了应用程序性能。 例如:

for (int i = 0; i <= 100; i ++)
    std::cout << i << "meters / s:" << "=" << i * (3600/1000) << "Km / h" << endl;

上面的例子显然是虚构的,但它只是为了说明情况。它可能是一个百万倍的循环,有数百个涉及重复常数的计算。

然后我问:

  1. “(3600/1000)”计算会在100次循环中重复运行吗?
  2. 这样,为了避免性能损失,我应该在循环之前将这个计算存储在一个常量变量中,并用该变量改变计算吗?
  3. 或者我不必担心它,因为c ++提供了一种自动优化这些情况的方法,以避免性能损失?
  4. 或者即使我改变3600为常数“a”而1000为常数“b”,也就是说,而不是3600/1000我有“a / b”,即使“a”和“b”是常数,但是操作是重复计算100次还是有任何优化?
  5. 我理解这个问题是相关的,因为它涉及应该采用的编程风格。

3 个答案:

答案 0 :(得分:2)

这听起来像是一个评论,但作为你担心的答案非常重要。

编译器比你聪明。

尝试编写快速代码时,这是一个非常好的经验法则。

编写可读的代码,编译器很可能会完成剩下的工作。

答案 1 :(得分:0)

不要担心您展示的代码段。恒定折叠是一种基本的优化技术。循环展开也是如此(特别是对于固定的迭代次数)。

您唯一需要的是激活优化的编译器标志:clang / GCC上的-O3(或其他),MSVC的/ O3。

即使代码完美无缺,我建议给你的魔术常量一个名字来提高可读性:

constexpr static const auto SECONDS_IN_HOUR = 3600;
constexpr static const auto METERS_IN_KILOMETER = 1000;
constexpr static const auto FACTOR_KILOMETER_PER_HOUR_TO_METERS_PER_SECOND = static_cast<double>(SECONDS_IN_HOUR) / static_cast<double>(METERS_IN_KILOMETER);

因为这是constexpr,所以这些应该在编译时计算,并且结果不会导致运行时开销。这甚至可以在没有启用优化的情况下工作。

请注意,从C ++ 17开始,这些常量是隐式内联的。因此,如果您使用旧的编译器,可能需要进行一些更改。

答案 2 :(得分:-1)

有些cpu会在自己的缓存中重复计算。

我的建议是将结果放在那里,所以它永远不必这样做。也总是使用大括号,以防你以后添加更复杂的结构。

for(int i = 0; i <= 100; i ++) {
    std::cout << i << "meters / s:" << "=" << i * 3.6 << "Km / h" << endl;
}

对于其他更复杂的对象,可能只运行直接需要结果的计算,或预先计算并存储结果以供日后使用。