首 页 | 新 闻 | Symbian | Android| Windows Mobile | J2ME | 下载中心 | 游戏策划招聘与求职 | 购书指南 | 视频教程
您现在的位置: 开发视界 >> Symbian >> 语言基础 >> 正文
几种std::vector访问方法的效率
作者:Jarod    文章来源:Jarod 的半个程序员    更新时间:2007-8-20 11:51:28
#define _SECURE_SCL 0

#include 
<boost/foreach.hpp>
#include 
<list>
#include 
<vector>
#include 
<algorithm>
#include 
<cstdlib>
#include 
<time.h>
#include 
<stdio.h>

using namespace std;

template
<typename Container>

void generate(typename Container & v) {
    size_t size 
=
 v.size();
    
for (size_t i=0; i< size ; ++i) 
{
        v[i] 
= i;//rand();

    }

}


struct case1 {
int operator() (const vector<int> & v, size_t size) 
{
    
int sum=0
;
    vector
<int>::const_iterator it =
 v.begin();
    
for (size_t i=0; i< size; ++i, ++it ) 
{
        sum 
+= *
it;
    }

    
return sum;
}
}
;

struct case2 
{
int operator() (const vector<int> & v, size_t size) 
{
    
int sum=0
;
    
for(size_t i=0; i< size; ++i) 
{
        sum 
+=
 v[i];
    }

    
return sum;
}
}
;

struct case3 
{
int operator() (const vector<int> & v, size_t size) 
{
    
int sum=0
;
    BOOST_FOREACH(
int x, v) 
{
        sum 
+=
 x;
    }
    
    
return
 sum;
}
}
;

struct case4 
{
int operator() (const vector<int> & v, size_t size) 
{
    
int sum=0
;
    
for (vector<int>::const_iterator it =
 v.begin();
        it 
!=
 v.end();
        
++
it
        ) 
{
        sum 
+= *
it;
    }

    
return sum;
}
}
;

template
<typename T>

__int64 Do(typename T op, vector
<int> &v, int M) {
    size_t size 
=
 v.size();
    __int64 sum 
= 0
;
    
for (int i=0;i<M;++i) 
{
        generate(v);
        sum 
+=
 op(v, size);
    }

    
return sum;
}


int main() {
    srand(static_cast
<unsigned int>
(time(NULL)) );

    vector
<int> v(65536
);
    
int M= 10000
;
    printf(
"1 : %d "
, Do(case1(),v,M));
    printf(
"2 : %d "
, Do(case2(),v,M));
    printf(
"3 : %d "
, Do(case3(),v,M));
    printf(
"4 : %d "
, Do(case4(),v,M));
    
}

 

debug模式下:

先不看case3,因为BOOST_FOREACH的效率在debug模式下与其它相差较大。Case4也不看

 

case1case2的效率基本相同。

注意case1中的主要操作是*++;而case2中主要是[]size(),特别的,size()还可以改STL原码除去,这样case2将大为缩短时间。

 

 

而在Release模式下,case2比case1略优:

 

 

通过跟踪可以发现:

vectorsize()函数里使用了一个三元操作符?:,而不是直接返回size,但这里没有安全检查。

operator*()++()中,即便在release版本中,都会包含指针检查(ASM中的__imp___invalid_parameter_noinfo部分),每个操作都包括_SCL_SECURE_VALIDATE_SCL_SECURE_VALIDATE_RANGE,但这些消耗的时间不多。两个检查若没通过都会转到__imp___invalid_parameter_noinfo中。

 

struct case1 {

int operator() (const vector<int> & v, size_t size) {

     int sum=0;

     vector<int>::const_iterator it = v.begin(); // 一个检查

     for (size_t i=0; i< size; ++i, ++it ) { // 一个检查

         sum += *it;   // 一个检查

     }

     return sum;

}};

 

struct case2 {

int operator() (const vector<int> & v, size_t size) {

     int sum=0;

     for(size_t i=0; i< size; ++i) {

         sum += v[i];//一个检查,但是包含求size()的检查

     }

     return sum;

}};

 

[]操作中,包括一个_SCL_SECURE_VALIDATE_RANGE(_Pos < size()),而求size()费时。

 

Case4中包含更多的安全检查。

 

要消除这些安全查检,可以定义_SECURE_SCL0

消除检查之后,得到如下结果。两种方式的效率已经相当接近,但case1还是略优。改写后的Case34也与前两者接近。

剩下的只能用vtune来分析每个操作了。

 

结论:不论用哪种方法,release版的效率都差不多。

1.       少使用size()

2.       使用[]访问,使调试与发布的运行效率接近。

相关文章:
没有相关文章
 

站点地图 | 加入收藏 | 联系站长 | 广告服务 |
QQ:280529124  Tel:0592-8271361 辽ICP备05021703号