2010-04-11 89 views
0

什么是更快和/或通常更好?矢量[] vs复制

vector<myType> myVec; 
int i; 
myType current; 

for(i = 0; i < 1000000; i ++) 
{ 
current = myVec[ i ]; 
doSomethingWith(current); 
doAlotMoreWith(current); 
messAroundWith(current); 
checkSomeValuesOf(current); 
} 

vector<myType> myVec; 
int i; 

for(i = 0; i < 1000000; i ++) 
{ 
doSomethingWith(myVec[ i ]); 
doAlotMoreWith(myVec[ i ]); 
messAroundWith(myVec[ i ]); 
checkSomeValuesOf(myVec[ i ]); 
} 

目前我使用的第一个解决方案。每秒钟真的有数百万次的调用,每一次比较/移动都会带来性能问题。

+14

为什么你在这里问人们哪里的速度更快,而不是在十分钟内写一个测试工具,以便给你一个明确的答案? – 2010-04-11 09:46:40

+3

当人们问布尔问题“哪一个更快”,而不是“多快多少”(就复杂度,CPU周期或时间而言)时,我总是感到惊讶 – 2010-04-11 10:09:07

+0

@Pavel:或者“在什么情况下更快” – jalf 2010-04-11 10:18:21

回答

0

取决于您的类型的赋值运算符。我希望通过参考这些函数来传递信息?但是对于所有性能问题,如果它对您很重要,请自己测试您的具体情况。

0

在格式方面,我建议以下(声明在初始化点,使用常量的myType &):

 
vector myVec; 
for(int i = 0; i < 1000000; i++){ 
const myType& current = myVec[i]; 
doSomethingWith(current); 
doAlotMoreWith(current); 
messAroundWith(current); 
checkSomeValuesOf(current); 
} 

然而,在你原来的问题方面,使用名为current是一个临时变量至少与每次使用myVec[i]一样快。不过,有可能优化编译器会删除myVec的冗余查找(即使用赋值给临时解决方案)......一般情况下,如果您重复调用一个声明为“const”的成员函数,而不使用任何非const成员函数,编译器可以自由创建一个临时对象并仅执行一次调用,将结果保存到本地临时对象中。

11

第一个版本可能是不必要的昂贵,因为它依赖于创建向量中对象的副本。除非myType是一些非常小且简单的对象,如int,存储参考可能是一个更好的主意。还应当申报当你需要它,并没有更早,限制走样的问题是威力否则会导致编译器发出代码效率不高:

创建副本的
vector<myType> myVec; 
for(int i = 0; i < 1000000; i ++) 
{ 
myType& current = myVec[ i ]; 
doSomethingWith(current); 
doAlotMoreWith(current); 
messAroundWith(current); 
checkSomeValuesOf(current); 
} 

一个优点,而不是使用引用是因为它可能会导致编译器将对象加载到寄存器中,而不是在每次访问时从内存中读取它。所以这两个版本都值得尝试。

任何当然,副本参考建议也适用于您的每个函数。他们是否通过价值或参考来进行论证?根据他们用它做什么,以及如何定义myType,可能会比另一个更快。

第二个版本是有缺陷的,因为它(除非编译器能够优化它)需要在每个时间内在内存中查找对象。根据您的STL实现,由于operator[]上的边界检查,可能还会有一些开销。

创建临时第一个,然后传递给您的每个函数是正确的路要走。问题在于是否该临时应值类型(myType),或引用类型(myType&/const myType&)的

另一种选择的是可以值得探讨是把在其自身的单独的循环中的每个函数调用。这在某些方面会伤害数据本地化,但如果某些功能使用大量本地数据,它可能会表现更好。它也可以在指令缓存中更好地发挥作用。

但实际上,性能非常复杂。高速缓存,乱序执行,myType的确切语义(特别是其拷贝构造函数和大小)以及编译器执行的优化量都不为我们所知。所以我们不能给你一个可靠的答案。

猜猜谁可以:你的编译器。写测试。试试两个。计时结果。选择更快的一个。

+0

bruno问:“有谁能向我解释为什么在循环中声明变量比在外部声明更好。” – Thomas 2010-04-11 10:43:36

1

除了避免多次访问相同的索引并使用引用以避免复制之外,您可以在函数中使用快速调用调用约定。它指示编译器在可能的情况下传递寄存器中的参数,而不是推送到堆栈。

但是,快速调用不是标准化的,所以它是供应商特定的。