2012-01-17 113 views
1
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))?

+3

我的猜测是,在第一种情况下,编译器不知道'size()'函数返回的值不会改变,所以它必须在每个循环中调用它。 – 2012-01-17 10:05:47

+0

你是怎么做时间/分析的?如果缓存温暖,那么第二个肯定会加快速度。同样,检查生成的ASM,你应该看到很少或没有改变。 – Necrolis 2012-01-17 10:07:35

+3

你打开了优化? – 2012-01-17 10:07:39

回答

5

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

如果它不能证明,呼叫不能移出循环。

2

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

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

1

A std::listcontainer是一个链表,并且计算它的大小可能是昂贵的(O(n)算法,它在最新的C++ 11标准IIRC中发生了变化)。编译器不知道函数的主体没有改变,所以它的大小在第一种情况下(在for循环的每次测试中)在每个循环中计算一次,并且在第二种情况下只计算一次。

也许你应该考虑使用std::vector来代替。

+0

所以'std :: list'没有一个简单的'size'成员可以返回?这令我失望。 – 2012-01-17 10:23:51

+0

我认为它在C++ 11中已经发生了变化,并且因为新的C++标准库(二进制)与旧版本不兼容。 – 2012-01-17 10:25:54

+1

@MrLister - 'std :: list'具有'splice'功能,可以在不同列表之间移动节点。在C++ 03中,选择是将'splice'设为恒定时间,这需要在'size'上进行设置。我相信C++ 11做出了不同的选择 - *一些*调用splice会花费线性时间。 – 2012-01-17 10:48:49