简体   繁体   中英

iterating over std containers using standard for

From what I've learned the way to iterating over container, as std::vector, is by using iterators, as this:

for(vector<int>::iterator it = numbers.begin(); it != numbers.end(); it++)

My question is why not not iterating over container with standatd for , it is faster, because there is no need to call functions as numbers.begin() , and numbers.end() .
From what I tried, I found that using for is faster X 30, from using iterators.
I wrote this code:

vector<int> numbers;
for (int i = 0; i < 5000000; i++)
{
    numbers.push_back(i);
}

time_t t = time(0);
struct tm * now = localtime(&t);
cout << now->tm_hour << ":" << now->tm_min << ":" <<  now->tm_sec << "\n";

for(vector<int>::iterator it = numbers.begin(); it != numbers.end(); it++)
{
    *it = 7;
}

t = time(0);
now = localtime(&t);
cout << now->tm_hour << ":" << now->tm_min << ":" <<  now->tm_sec << "\n";

int size = numbers.size();
for (int i = 0; i < size; i++)
{
    numbers[i] = i;
}

t = time(0);
now = localtime(&t);
cout << now->tm_hour << ":" << now->tm_min << ":" <<  now->tm_sec;

The output is:

    19:28:25
    19:28:56
    19:28:57

Look at your numbers -- 30 seconds to iterate a simple vector? That's an eternity in CPU time. There's something wrong there.

Some suggestions:

  • The vector takes ~19MB. That's not much but it's possible that it could cause heap fragmentation, or maybe VM swapping if you had many other apps loaded on your computer. To get a reliable number, close as many apps as possible and make sure your system is idle.

  • The couts are inside the timer, so you're measuring the performance of parts of the iostream library. Do the couts outside the timed section, after you take the stop time.

  • A one-second clock isn't precise enough for performance metrics. Use timeval and gettimeofday() to get micro-second precision.

  • With only one iteration of the vector, I was seeing big diffences between runs. To get more repeatable results, iterate the vector multiple times (like 500 times). (This is better than using a larger vector, which might cause swapping/fragmentation issues.)

  • Turn on optimizations (eg, g++ -O3). The loops will ran much faster and the time difference will be much less. Inline optimizations probably help the std::vector<> code more.

With these changes (below), on my computer, iterators were 4x slower than indicies without optimizations but slightly faster with -O1 and pretty much the same with -O3.

#include <iostream>
#include <sys/time.h>
#include <vector>
using namespace std;

const unsigned N_REPS = 500;
const unsigned N_ITEMS = 5000000;

int print_elapsed(timeval start)
{
    timeval stop;
    gettimeofday(&stop, NULL);
    int elapsed = (stop.tv_sec * 1000000 + stop.tv_usec) - (start.tv_sec * 1000000 + start.tv_usec);
    cout << elapsed << "us" << endl;
    return elapsed;
}

int main()
{
    vector<int> numbers;
    numbers.reserve(N_ITEMS); // avoid heap fragmentation
    for (int i = 0; i < N_ITEMS; ++i)
        numbers.push_back(i);

    timeval start;
    gettimeofday(&start, NULL);

    for (unsigned r = 0; r < N_REPS; ++r)
        for (vector<int>::iterator it = numbers.begin(); it != numbers.end(); ++it)
            *it = r;

    int elapsed0 = print_elapsed(start);
    gettimeofday(&start, NULL);

    unsigned size = numbers.size();
    for (unsigned r = 0; r < N_REPS; ++r)
        for (unsigned i = 0; i < size; ++i)
            numbers[i] = r;

    int elapsed1 = print_elapsed(start);
    cout << 100 * float(elapsed1) / elapsed0 << '%' << endl;

    return 0;
}

Using iterators provide you the flexibility that even if you change the container type to another the iterating code will remain the same. This is because all the standard library containers provide iterators. In a way it gives you the chance to write more generic code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM