Posted by: rmn on: 28/08/2009
Iterating over a vector is a pretty simple task we get to do pretty often. It can be achieved in quite a few ways:
I set out to check the runtime differences between all these options, and the results turned out to be a little surprising (or not).
Let me present the setup:
#include <algorithm>
#include <vector>
typedef std::vector<int> vec;
struct func {
void operator () (int &n) const {
n *= 2;
}
};
void idx (vec &v, func &f) {
for (size_t i=0;i<v.size();++i)
f(v[i]);
}
void iterate (vec &v, func &f) {
for (vec::iterator i=v.begin();i!=v.end();++i)
f(*i);
}
void foreach (vec &v, func &f) {
std::for_each(v.begin(), v.end(), f);
}
I used the Timer class (presented here) to time all the different options, in the following manner:
#include "timer.hpp"
int main () {
Timer t("iterate");
vec v(30000, 2);
func f;
for (unsigned i=30000;i;--i)
iterate(v, f);
return 0;
}
The tests were run on my own system; Windows Vista, Visual Studio 2008 (release config), Intel core2 quad q9450, 4gb ram. The observed results were the following:
idx: 1.188secs.
iterate: 6.813secs.
foreach: 0.709secs.
Looks like using the foreach algorithm is the fastest way, followed by normal random-access (using operator[]), while the usage of iterators seems to be the slowest by far.
Edit: as it turns out, the usage of checked iterators is enabled in visual studio by default, both in debug and in release modes. As you could guess, this fact has a great effect on the results. When the feature is disabled (#define _SECURE_SCL 0), the results are totally different; std::for_each still wins, but the margins are significantly smaller:
idx: 0.686secs.
iterate: 0.701secs.
foreach: 0.682secs.
I would like to thank Halbling for raising the question.
Er, and:
void idx (vec &v, func &f) {
size_t n = v.size();
for (size_t i = 0;i < n; ++i)
f(v[i]);
}
These can't be cached as the compiler does not know if f() has side-effects on the vector. Consequently, using my functions you have to ensure that it doesn't, but if it did then it wouldn't be a very good iteration benchmark would it.
On linux (Athlon XP 1600+, g++ -O3), I get the following times for the original versions:
> idx: 1.584 s
> iterate: 1.715 s
> foreach: 1.560 s
Seems like gcc does some decent optimizations.
Also make sure that Visual Studio does not use the range-checking iterators in your benchmark…
Another way is Boost.Foreach : http://www.boost.org/doc/libs/1_39_0/doc/html/foreach.html .
vector myvector;
BOOST_FOREACH( int i , myvector )
cout << i;
The code is optimal as for with iterator and caching the end.
(Checked on MSVC 2008 )
28/08/2009 at 15:09
Ew, calculating .end() on every iteration? No.
void iterate (vec &v, func &f) {
vec::iterator it = v.begin(), end = v.end();
for ( ; it != end; ++it)
f(*it);
}
Try again!
Also, is there something wrong with your SHIFT-key?
Regards