C++ 将vector size()从循环条件中取出以进行优化
fibs是一个std::向量。使用g++时,有人建议我将fibs.size()从循环中去掉,以节省每次计算的时间(因为向量可能会改变)C++ 将vector size()从循环条件中取出以进行优化,c++,C++,fibs是一个std::向量。使用g++时,有人建议我将fibs.size()从循环中去掉,以节省每次计算的时间(因为向量可能会改变) int和=0; 对于(int i=0;i
int和=0;
对于(int i=0;i
当然,编译器中有一些数据流分析会告诉我们fibs不会改变大小。有?或者我应该将其他变量设置为fibs.size()并在循环条件中使用它吗?编译器可能会确定它不会更改。即使是这样,向量的
size()
也是一个O(1)操作。除非您知道这是一个问题,否则请保持原样。首先要使它正确,然后使它清楚,然后使它快速(如果必要的话)
无论如何,vector::size
速度非常快。在我看来,编译器可能会对这种情况进行优化,因为很明显,向量没有被修改,所有调用的函数都将内联,因此编译器可以判断
您可以随时查看生成的代码,看看是否发生了这种情况
如果你真的想改变它,你需要能够测量它前后所花费的时间。这是一个相当大的工作量-你可能有更好的事情要做。size()是一个常数时间操作,这样叫没有任何惩罚。如果您关心性能和使用更通用的方法遍历集合,请使用迭代器:
int sum = 0;
for(auto it = fibs.cbegin(); it != fibs.cend(); ++it) {
if((*it) % 2 == 0){
sum += *it;
}
}
在您的示例中,编译器可以轻松地分析流,并确定它不会改变。在更复杂的代码中,它不能:
for(int i = 0; i < fibs.size(); ++i){
complicated_function();
}
for(int i=0;i
复杂的函数
可以更改fibs
。但是,由于上面的代码涉及函数调用,编译器无法在寄存器中存储fibs.size()
,因此无法消除内存访问。我认为您缺少了另一个更重要的点:此循环是否会导致应用程序的速度减慢?如果您不确定(即,如果您尚未分析),则可能会将注意力集中在应用程序的错误部分
在编写程序时,您已经需要记住成千上万的事情(编码准则、应用程序的体系结构(大图)、变量名、函数名、类名、可读性等),您可以在初始实现过程中忽略代码的速度(至少95%的时间)。这将使您能够专注于更重要、更有价值的事情(如正确性、可读性和可维护性)。1+1+2+3+5+…+Fn=Fn+2-1。因此,建议您的人不希望每次都计算
大小
(g++中的减法,在优化之前),但不介意调用操作符[]
(与优化之前使用迭代器相比,还有额外的加法)两次。什么,甚至永远。最好是查看发出的指令,或者对其计时。Steve,如果我知道向量的大小保证不会改变,那么使用运算符[]是否可以节省时间?此外,我是一个C++小丑。那么,使用迭代器更快吗?@shuttle87:我是说,如果有人(给出此建议的人)打算对性能做出疯狂的概括,我有点惊讶,他们猜测size()
比访问变量慢,但他们没有猜到运算符[]
比使用迭代器或指针慢。我猜不出优化器会做什么——它实际上可能会设法用指针替换索引I
,但要做到这一点,它必须以某种方式说服自己,向量永远不会重新分配,这几乎比说服自己它可以提升大小
的值容易得多。基本问题是操作符[]
必须从向量对象中加载向量的基指针(并添加索引),就像gcc上的size()
从向量对象中加载基指针和结束指针(并减去它们)。因此,在这两种情况下,这几乎是一种精巧的微观优化。就个人而言,我不会担心这两个问题,直到这段代码被证明是瓶颈,然后检查发出的代码。但如果你要担心其中一个,我认为你应该同时担心这两个。O(1)只说它是有界的。这仍然可能是昂贵的(好吧,不是一个向量)。
for(int i = 0; i < fibs.size(); ++i){
complicated_function();
}