#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也不看
case1與case2的效率基本相同。
注意case1中的主要操作是*和++;而case2中主要是[]和size(),特別的,size()還可以改STL原碼除去,這樣case2將大爲縮短時間。
而在Release模式下,case2比case1略優:
通過跟蹤可以發現:
vector的size()函數裏使用了一個三元操作符?:,而不是直接返回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_SCL爲0。
消除檢查之後,得到如下結果。兩種方式的效率已經相當接近,但case1還是略優。改寫後的Case3和4也與前兩者接近。
剩下的只能用vtune來分析每個操作了。
結論:不論用哪種方法,release版的效率都差不多。
1. 少使用size()。
2. 使用[]訪問,使調試與發佈的運行效率接近。
|