从性能的角度来看,更快的是什么?

时间:2014-05-06 11:29:51

标签: c++ performance gcc compiler-optimization

从性能角度来看哪个顺序实现会更快(我确实意识到第二个需要更多的内存和时间来在RAM中写入值):

for(int j=3; j<=ceil(sqrt(i));j++){
...
}

vs

int max=ceil(sqrt(i));
for(int j=3; j<=max;j++){
...
}

它与编译器如何处理此代码有关。欢迎任何关于在哪里寻找答案的提示。

P.S。: Plz并不建议通过运行它来大胆直接地检查性能。我必须提醒一下,底层系统的架构可能会有很大差异。因此,第一种情况可能在一种架构上获胜,而第二种情况可能在另一种架构上占主导地这就是为什么我需要对两者进行明确定义的处理。这可能是编译器规范,让我们将案例限制为gcc。从哪一点来看问题是:我会查找哪个编译器规范部分来查找它?

2 个答案:

答案 0 :(得分:2)

我认为这取决于。如果编译器能够证明在执行循环期间i没有被改变,则常量传播可以删除对sqrt()和ceil()的重复评估。如果编译器在执行期间无法确定i是否为常量,则除了在第一个示例中反复评估ceil(sqrt())之外别无选择。

答案 1 :(得分:0)

我做了一些测量并使用了底部的代码(也可以随意使用)。

  • VC2013的结果(intel core i3 1.80GHz):
  TIME FUN1 = 73.8 milli-seconds
  TIME FUN2 = 72.2 milli-seconds
  • GCC v4.7.2中的结果(没有特征):
  TIME FUN1 = 23.7 milli-seconds
  TIME FUN2 = 23.5 milli-seconds

似乎第二种方法略胜一筹(我认为这是预期的)。但是,数量级并不慢。在我的拙见中,差异非常小,最终得出一个安全的结论。显然,编译器优化和系统架构起着重要作用。

#include <iostream>
#include <cmath>
#include <chrono>

// facility to measure time
template<typename TimeT = std::chrono::milliseconds>
struct ExecTime
{
    template<typename F>
    static typename TimeT::rep exec(F const &func)
    {
        auto start = std::chrono::system_clock::now();
        func();
        auto duration = std::chrono::duration_cast< TimeT>(
            std::chrono::system_clock::now() - start);
        return duration.count();
    }
};

// dummy function to call in loop
void dummy() { int a = 0; }

int main()
{
  int const iters = 30;
  double d = 999999999999.0;
  auto fun1 = [&]() {for (int j = 3; j <= ceil(sqrt(d)); j++) dummy();};
  auto fun2 = [&]() {int max = ceil(sqrt(d)); for (int j = 3; j <= max; j++) dummy(); };

  double time1 = 0.0;
  for(int i = 0; i < iters; ++i) {
    time1 += ExecTime<>::exec(fun1);
  }
  double time2 = 0.0;
  for (int i = 0; i < iters; ++i) {
    time2 += ExecTime<>::exec(fun1);
  }
  std::cout << "TIME FUN1 = " << time1 / static_cast<double>(iters) << " milli-seconds" << std::endl;
  std::cout << "TIME FUN2 = " << time2 / static_cast<double>(iters) << " milli-seconds" << std::endl;

  return(0);
}