使向量大小()脱离循环条件进行优化

Posted

技术标签:

【中文标题】使向量大小()脱离循环条件进行优化【英文标题】:Taking vector size() out of loop condition to optimize 【发布时间】:2011-06-18 11:04:09 【问题描述】:

fibs 是一个 std::vector。使用 g++,我被建议将 fibs.size() 退出循环,以节省每次计算它(因为向量可能会改变)

int sum = 0;
for(int i = 0; i < fibs.size(); ++i)
    if(fibs[i] % 2 == 0)
        sum += fibs[i];
    

编译器中肯定有一些数据流分析会告诉我们 fibs 不会改变大小。有没有?或者我应该将其他一些变量设置为 fibs.size() 并在循环条件中使用它?

【问题讨论】:

1 + 1 + 2 + 3 + 5 + ... + Fn = Fn+2 - 1. 因此,无论谁建议您都不希望每次都计算 size(g++ 中的减法,在优化之前),但不介意调用 operator[](以及比较的额外加法)在优化之前使用迭代器)两次。什么,确实如此。最好是查看发出的指令,或者计时。 Steve,如果我知道向量的大小保证不会改变,那么使用 operator[] 不只是节省时间吗?另外,我是一个 C++ 小丑。那么使用迭代器是否更快? @shuttle87:我是说 如果 有人(无论谁给出了这个建议)将对性能做出疯狂的概括,我有点惊讶他们是猜测size() 比访问变量慢,但他们并没有猜测operator[] 比使用迭代器或指针慢。我不会准确猜测优化器会做什么——它实际上可能会设法用指针替换索引i,但要这样做,它必须以某种方式说服自己向量永远不会重新分配,这几乎比说服自己容易它可以提升size的值。 基本问题是operator[] 必须将向量的基指针从向量对象中加载出来(并添加索引),就像 gcc 上的 size() 将基指针和结束指针加载出来一样矢量对象的(并减去它们)。因此,在这两种情况下,它几乎是同一种繁琐的微优化。就我个人而言,在这段代码被证明是瓶颈之前,我不会担心它们,然后检查发出的代码。但是,如果您要担心一个,我认为您应该同时担心两者。 【参考方案1】:

编译器可能会确定它不会改变。即使是这样,向量的size() 也是一个 O(1) 操作。

【讨论】:

O(1) 只说它是有界的。它仍然可能很昂贵(好吧,不是矢量)。【参考方案2】:

除非您知道这是个问题,否则请保持原样。先正确,再清楚,再快速(如有必要)。

vector::size 无论如何都非常快。在我看来,编译器很可能会优化这种情况,因为很明显向量没有被修改,所有调用的函数都将被内联,以便编译器知道。

您可以随时查看生成的代码,看看是否发生了这种情况。

如果你确实想改变它,你需要能够测量它之前和之后所花费的时间。这是相当多的工作 - 你可能有更好的事情要做。

【讨论】:

【参考方案3】:

size() 是恒定时间操作,这样调用它没有任何惩罚。如果您担心性能和更通用的遍历集合的方法,请使用迭代器:

int sum = 0;
for(auto it = fibs.cbegin(); it != fibs.cend(); ++it) 
    if((*it) % 2 == 0)
        sum += *it;
    

【讨论】:

【参考方案4】:

我认为您在这里遗漏了另一个更重要的观点:这个循环是否会导致您的应用程序变慢?如果您不确定(即,如果您没有分析),您可能会关注应用程序的错误部分。

在编写程序时,您已经不得不将成千上万的事情记在脑海中(编码指南、应用程序的架构(大图)、变量名、函数名、类名、可读性等),您可以忽略速度初始实现期间的代码(至少 95% 的时间)。这将使您能够专注于更重要和更有价值的事情(例如正确性、可读性和可维护性)。

【讨论】:

【参考方案5】:

在您的示例中,编译器可以轻松分析流程并确定它没有改变。在更复杂的代码中它不能:

for(int i = 0; i < fibs.size(); ++i)
    complicated_function();

complicated_function 可以更改fibs。但是,由于上述代码涉及函数调用,编译器无法将fibs.size() 存储在寄存器中,因此您无法消除内存访问。

【讨论】:

以上是关于使向量大小()脱离循环条件进行优化的主要内容,如果未能解决你的问题,请参考以下文章

sql语句中where后边的哪些条件会使索引失效 -- SQL语句优化

Java程序性能优化

Java程序性能优化

Java程序性能优化总结

[JAVA] java程序性能优化

支持向量机:图解KKT条件和拉格朗日乘子法