【问题标题】:g++ compiler optimizationg++编译器优化
【发布时间】:2012-02-12 03:25:52
【问题描述】:
list<mpz_class> baseFactor;

1)

int *tab = new int [baseFactor.size()]; //baseFactor.size() ~= 20000
for(i = 0; i < baseFactor.size(); i++){
  cout << tab[i] << endl;
}

// Total time: 2.620790

2)

int size = baseFactor.size();
int *tab = new int [size]; //baseFactor.size() ~= 20000
for(i = 0; i < size; i++){
  cout << tab[i] << endl;
}

//Total time: 0.366500

为什么 g++ 编译器没有在 2) 中优化代码 1) ?

【问题讨论】:

  • 我的猜测是,在第一种情况下,编译器不知道 size() 函数返回的值不会改变,所以它必须在每个循环中调用它。
  • 你是如何进行计时/分析的?如果缓存是热的,那么第二个肯定会加快速度。此外,检查生成的 ASM,您应该几乎看不到任何变化。
  • 你开启优化了吗?
  • 在#2 中,将“size”声明为“const int”而不是简单的“int”。并在 for 循环中将“i”声明为内联变量“for (int i = 0; i

标签: c++ optimization g++


【解决方案1】:

根据baseFactor 的定义位置(全局变量?),编译器可能很难证明size() 总是返回相同的值。

如果不能证明这一点,则不能将调用移出循环。

【讨论】:

    【解决方案2】:

    对于要优化到第二个的第一个,它将要求 baseFactor.size() 在循环期间永远不会改变。

    当然可能不知道,但是编译器知道吗?

    【讨论】:

      【解决方案3】:

      std::listcontainer 是一个链表,计算其大小可能代价高昂(O(n) 算法,在最新的 C++11 标准 IIRC 中已更改)。编译器不知道你的函数体没有改变basefactor,所以它的大小在第一种情况下的每个循环中计算一次(在for循环的每次测试中),而在第二种情况下只计算一次。

      也许您应该考虑改用std::vector

      【讨论】:

      • 所以std::list 没有可以返回的简单size 成员?这让我很失望。
      • 我认为它在 C++11 中有所改变,因此新的 C++ 标准库(二进制)与旧的不兼容。
      • @MrLister - std::list 有一个 splice 函数,可以在不同列表之间移动节点。在 C++03 中,选择是让 splice 保持恒定时间,这需要在 size 上放弃它。我相信 C++11 做出了不同的选择 - 一些 调用splice 将花费线性时间。
      • @BoPersson:在 C++11 (23.3.5.5 [list.ops]) 中,splice 是常数时间,而 splice(const_iterator pos, list&lt;&gt;&amp;&amp;, const_iterator first, const_iterator last) 重载是线性的(除非它是在这种情况下它是恒定的)。此外,list 现在完全支持序列要求(不再有特殊情况)。所以是的,size() 现在也是列表的固定时间。
      猜你喜欢
      • 2017-11-06
      • 2012-09-05
      • 1970-01-01
      • 2011-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-21
      • 2011-08-24
      相关资源
      最近更新 更多