Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon.

Pages: 1-4041-

C++

Name: Snake4D 2012-04-11 17:38

A simple question...

is it better to traverse a std::vector like this:

std::vector<int> myvec;
//populate the vector
for(int i = 0; i < myvec.size(); ++i){
    myvec[i] += 1;
}


or is better like this?

std::vector<int> myvec;
typedef std::vector<int>::iterator IT_int;
for(IT_int it = myvec.begin(); it != myvec.end(); ++it){
     *it += 1;
}

Name: Anonymous 2012-04-11 17:52

#include <iostream>
#include <vector>
#include <ctime>

int main (int argc, char * const argv[]) {
    std::vector<int> myvec;
    for (int i = 0; i < 100000000; ++i) {
        myvec.push_back(i);
    }
    typedef std::vector<int>::iterator IT_int;
   
    clock_t start,end;
   
    start = std::clock();
    for (IT_int it = myvec.begin(); it != myvec.end(); ++it) {
        *it += 1;
    }
    end = std::clock();
   
    std::cout << end - start << std::endl;
   
    start = std::clock();
    for (int i = 0; i < myvec.size(); ++i) {
        myvec[i] += 1;
    }
    end = std::clock();
   
    std::cout << end - start << std::endl;
   
    return 0;
}


output:

1st try:
2858863
1135227

2nd try:
2461235
1139648

3rd try:
2618116
1133062


compiled with XCode 3.2.5, GCC 4.2

Name: Anonymous 2012-04-11 18:05

Just use an array.

Name: Anonymous 2012-04-11 18:11

>>1
Strictly speaking you should use iterators. It has the advantage of just being a pointer, but that said, I think C++ ideologies like these are just plain silly.

Name: Anonymous 2012-04-11 18:14

#include <iostream>
#include <vector>
#include <ctime>

#define SIZETOTEST 100000

int main (int argc, char * const argv[]) {
   
    std::vector<int> myvec;
    int myarray[SIZETOTEST];
   
    for (int i = 0; i < SIZETOTEST; ++i) {
        myvec.push_back(i);
        myarray[i] = i;
    }
    typedef std::vector<int>::iterator IT_int;
   
    clock_t start,end;
   
    start = std::clock();
    for (IT_int it = myvec.begin(); it != myvec.end(); ++it) {
        *it += 1;
    }
    end = std::clock();
   
    std::cout << "iterator it:   " << end - start << std::endl;
   
    start = std::clock();
    for (int i = 0; i < myvec.size(); ++i) {
        myvec[i] += 1;
    }
    end = std::clock();
   
    std::cout << "int i:         "<< end - start << std::endl;
   
    start = std::clock();
    for (int i = 0; i < SIZETOTEST; ++i) {
        myarray[i] = myarray[i] + 1;
    }
    end = std::clock();
    std::cout << "c-style array: " << end - start << std::endl;
   
    return 0;
}


a little deeper analysis:
in debug mode (no or really few optimization):

iterator it:   2430
int i:         1141
c-style array: 561


in release mode:

iterator it:   108
int i:         160
c-style array: 2


amazing... the iterator get faster than the normal access... (the c_style array optimization is also crazy...)

Name: Anonymous 2012-04-11 20:11

>>5
With the vector, you're potentially doing 100,000 reallocs and bounds checks, but with the array, you're just storing at an offset to a register.

Name: Anonymous 2012-04-12 0:16

>>6
push_back has order one amortized time according to the best resource to seeples on the internat http://www.cplusplus.com but I agree that it should be avoided in favor of performing a single call to resize and then modification by the [] operator.

>>5
one way to implement a vector iterator would be a direct pointer to a place in the vector's array. And then the tests, it == vec.end() can be performed by comparing the value of the pointer to the address just after the end of the used part of the array. If you were to use indexing on a C array, the compiler can handle optimizing away the index if necessary.

http://en.wikipedia.org/wiki/Loop-invariant_code_motion

Name: Anonymous 2012-04-12 0:29


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


Frivolous typedef considered UNREADABLE

Name: Anonymous 2012-04-12 0:34

>>5
the iterator get faster than the normal access

Because the optimizer can treat it as a pointer in some cases.

If you don't need vector functionality, then it's stupid to use them instead of C arrays.

Name: Anonymous 2012-04-12 1:06

>>9
That's really sad. There's no reason for vector iteration to be so much more inefficient than c array iteration. Although, to be fair, >>5 should do a test with a non statically allocated array. And >>5 should check the assembly output to see if the compiler is just culling out the c array iteration code, because the compiler might know that the code doesn't do anything meaningful or used later, whereas with the vector it might not be able to figure that out.

Name: Anonymous 2012-04-12 3:18

should be

for(std::vector<int>::iterator i = myvec.begin(), e = myvec.end(); i < e; i++) {


but it doesn't matter for the other one. This will probably make a difference even in release mode since myvec.end() isn't guaranteed to be invariant between calls (mutation by other threads, &c)

Name: Anonymous 2012-04-12 3:20

>>11
er, obviously i != e there instead

Name: Anonymous 2012-04-12 5:11

>>2-12 ARE YOU FAGGOTS EH?
>>1

    BOOST_FOREACH(int & it, myvec)
    {
        it += 1;
    }

Name: Anonymous 2012-04-12 5:16

C++11 is the best.


for(int& item : myvec) {
    item += 1;
}


Other way could be to use std::for_each with lambda, but I generally prefer range based for-loop.

Name: Anonymous 2012-04-12 5:36

>>14
Haskell is the best


map (+ 1) myvec

Other way could be to use pattern matching, but I generally prefer built-in functions.

Name: Anonymous 2012-04-12 5:38

c++ is such an abomination

Name: VIPPER 2012-04-12 5:50

C++ makes all other abominations look good in comparsion.

Its just screaming please kill me.

Name: JEW 2012-04-12 6:32

>>17 is just screaming please give me some toilets to scrub!

Name: Anonymous 2012-04-12 6:46

>>15
Too bad it has GC. Haskell is not the best. GC is shit.

Name: Anonymous 2012-04-12 7:24

would someone bugger me?

Name: Anonymous 2012-04-12 8:25

Wow. I'm surprised that there is really difference in speed between these versions. I thought optimizers in -O3 already could optimize out differences. Alas.

Well, anyway I prefer iterator approach as in debug mode it checks ranges.

Name: Anonymous 2012-04-12 8:45

Well, anyway I prefer index approach as in /prog/ mode it checks dubs.

Name: Anonymous 2012-04-12 12:58

What kind of shitty compilers are you using to get results like that?

With gcc traversing a vector with an iterator or an unsigned int as well as traversing an array are all equally fast. Iterating with signed int is about 20% slower which I guess is because gcc doesn't change the < comparison to != then, and equality comparisons are often a bit faster.

Name: Anonymous 2012-04-12 13:42

>>23
equality comparisons are often a bit faster.
Stop it, I'm crying.

Name: Anonymous 2012-04-12 13:43

>>23
laughing_whores.fif
lrn2cpu

Name: Anonymous 2012-04-12 14:42

Comparing (x < y) is O(n) because it checks (x == 0 || x == 1 || ... || x == y-1)

Name: Anonymous 2012-04-12 14:53

>>26
It's actually a O(n) SUB operation (x-y) and then followed by a check to see if the sign bit is 1

Name: Anonymous 2012-04-12 14:56

>>14
oh lawdy it's like C++ is taking a turn for java syntax sugar

Name: Anonymous 2012-04-12 15:07

>>26
Yeah, and comparing (x!=y) is O(n) because it checks (x_0!=y_0 || x_1!=y_1 || ... || x_{n-1)!=y_{n-1}).  Also you're a shit troll and a faggot.

Name: Anonymous 2012-04-12 15:38

>>26,27,29
It's actually O(1) since it only does 2*INT_MAX+1 comparisons and INT_MAX is a compile time constant.

Now fuck off shitty trolls.

Name: Anonymous 2012-04-12 16:28

>>27
>subtraction
>O(n) operation
How's that 1960s CPU doing for ya?

Name: Anonymous 2012-04-12 16:31

>>31
sadfrog.png

Name: kodak_gallery_programmer !!kCq+A64Losi56ze 2012-04-12 17:14

And the special olympics of computer science continues...

Name: Anonymous 2012-04-12 17:57

>>33
Life without a job must leave you with more time to troll and shitpost kodak-san

Name: kodak_gallery_programmer !!kCq+A64Losi56ze 2012-04-12 20:25

>>34
I'm gonna pursue my Ph.D in computational fluid dynamics at UCLA this fall.

Name: Anonymous 2012-04-12 20:26

Ph.D in computational fluid dynamics
What? Why is this a subject of Ph.D study?

Name: Anonymous 2012-04-12 22:44

>>36 PHDs are like that, all specific and shit.

Name: Anonymous 2012-04-12 22:49

>>29
that can actually be O(log(n)) where n is the number of bits, by using a balanced tree of or gates. And the same applies to x == y operation, except you would use and gates.

Name: Anonymous 2012-04-12 22:54

>>35
I'm gonna pursue my BA in toilet scrubbing at anywhere that will hire me forever.

Name: >>38 2012-04-12 23:38

err rather nands and nors or whatever is appropriate.

Name: Anonymous 2012-04-13 0:19

neither nands nor nors are as appropriate as or and/or and

Name: Anonymous 2012-04-13 0:22

This thead is full of idiots. Just use C++11.

Name: Anonymous 2012-04-13 0:24

>>42

s/++//

>>44

Nice dbus.

Name: Anonymous 2012-04-13 0:27

Name: Anonymous 2012-04-13 0:49

Total of elements: 200000
Heap array:
  using index:  0.001267s wall, 0.000000s user + 0.000000s system = 0.000000s CPU (n/a%)
  using std::for_each:  0.000275s wall, 0.000000s user + 0.000000s system = 0.000000s CPU (n/a%)

Stack array:
  using index:  0.000295s wall, 0.000000s user + 0.000000s system = 0.000000s CPU (n/a%)
  using std::for_each:  0.000270s wall, 0.000000s user + 0.000000s system = 0.000000s CPU (n/a%)
  using BOOST_FOREACH:  0.000995s wall, 0.015600s user + 0.000000s system = 0.015600s CPU (n/a%)

Vector:
  using index:  0.000296s wall, 0.000000s user + 0.000000s system = 0.000000s CPU (n/a%)
  using iterators:  0.000549s wall, 0.000000s user + 0.000000s system = 0.000000s CPU (n/a%)
  using std::for_each:  0.000533s wall, 0.000000s user + 0.000000s system = 0.000000s CPU (n/a%)
  using BOOST_FOREACH:  0.000582s wall, 0.000000s user + 0.000000s system = 0.000000s CPU (n/a%)

List:
  using iterators:  0.004329s wall, 0.000000s user + 0.000000s system = 0.000000s CPU (n/a%)
  using std::for_each:  0.009227s wall, 0.015600s user + 0.000000s system = 0.015600s CPU (169.1%)
  using BOOST_FOREACH:  0.007076s wall, 0.000000s user + 0.000000s system = 0.000000s CPU (n/a%)


#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
#include <boost/timer/timer.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/foreach.hpp>

const static size_t maxsz = 2e5;

boost::lambda::placeholder1_type X;

int main() {
    std::cout << "Total of elements: " << maxsz << std::endl;
    boost::random::mt19937 rng;
    {
        unsigned int* harr = new unsigned int[maxsz];
        for (int i = 0; i < maxsz; ++i) {
            harr[i] = rng();
        }
        std::cout << "Heap array:\n  using index: ";
        {
            boost::timer::auto_cpu_timer t;
            for (int i = 0; i < maxsz; ++i) {
                harr[i] /= 100;
            }
        }
        std::cout << "  using std::for_each: ";
        {
            boost::timer::auto_cpu_timer t;
            std::for_each(harr, harr+maxsz, X = X / 100);
        }
        std::cout << std::endl;
        delete[] harr;
    }

    {
        unsigned int arr[maxsz];
        for (int i = 0; i < maxsz; ++i) {
            arr[i] = rng();
        }
        std::cout << "Stack array:\n  using index: ";
        {
            boost::timer::auto_cpu_timer t;
            for (int i = 0; i < maxsz; ++i) {
                arr[i] /= 100;
            }
        }
        std::cout << "  using std::for_each: ";
        {
            boost::timer::auto_cpu_timer t;
            std::for_each(arr, arr+maxsz, X = X / 100);
        }
        std::cout << "  using BOOST_FOREACH: ";
        {
            boost::timer::auto_cpu_timer t;
            BOOST_FOREACH(unsigned int& i, arr) {
                i /= 100;
            }
        }
        std::cout << std::endl;
    }

    {
        std::vector<unsigned int> vec(maxsz);
        for (int i = 0; i < maxsz; ++i) {
            vec.push_back(rng());
        }
        std::cout << "Vector:\n  using index: ";
        {
            boost::timer::auto_cpu_timer t;
            for (int i = 0; i < maxsz; ++i) {
                vec[i] /= 100;
            }
        }
        std::cout << "  using iterators: ";
        {
            boost::timer::auto_cpu_timer t;
            const std::vector<unsigned int>::iterator end = vec.end();
            for (std::vector<unsigned int>::iterator it = vec.begin(); it != end; ++it) {
                *it /= 100;
            }
        }
        std::cout << "  using std::for_each: ";
        {
            boost::timer::auto_cpu_timer t;
            std::for_each(vec.begin(), vec.end(), X = X / 100);
        }
        std::cout << "  using BOOST_FOREACH: ";
        {
            boost::timer::auto_cpu_timer t;
            BOOST_FOREACH(unsigned int& i, vec) {
                i /= 100;
            }
        }
        std::cout <<std::endl;
    }

    {
        std::list<unsigned int> list(maxsz);
        for (int i = 0; i < maxsz; ++i) {
            list.push_back(rng());
        }
        std::cout << "List:\n  using iterators: ";
        {
            boost::timer::auto_cpu_timer t;
            const std::list<unsigned int>::iterator end = list.end();
            for (std::list<unsigned int>::iterator it = list.begin(); it != end; ++it) {
                *it /= 100;
            }
        }
        std::cout << "  using std::for_each: ";
        {
            boost::timer::auto_cpu_timer t;
            std::for_each(list.begin(), list.end(), X = X / 100);
        }
        std::cout << "  using BOOST_FOREACH: ";
        {
            boost::timer::auto_cpu_timer t;
            BOOST_FOREACH(unsigned int& i, list) {
                i /= 100;
            }
        }
        std::cout << std::endl;
    }

    return 0;
}

Name: Anonymous 2012-04-13 1:07

Money are dopamine of the hive mind, while central banks, like IMF, are the dopamine emitters, which are controlled mostly by the Jews. Kill all the Jews and you'll kill the globalization Hydra. There should be no mercy to the Jews, because they are the neurons of our Enemy.

Remember: it's these dollars, the Jews print, make your life bad, so every Jew you kill will make your country better. Help your nation's economic and culture - kill Jewish internationalists.

Name: Anonymous 2012-04-13 2:40

>>24
>>25
Why is that wrong? On x86 gcc uses cmp to implement < and test-instruction to implement !=. What else do think causes the difference in speed if the only difference in generated loops is that one uses cmp and one uses test?

Name: Anonymous 2012-04-13 6:30

>>47
Check your facts.

Name: Cudder !MhMRSATORI!FBeUS42x4uM+kgp 2012-04-13 6:41

>>47
Caches, alignment, other instructions, etc.

cmp and test are both single-cycle.

Name: Anonymous 2012-04-13 7:48

>>47
Not who you are replying to, but:

Equality could be tested for with n XOR gates and a dumb population count of OR gates (lg n)-1 levels deep. This gives you a time complexity of (lg n) to do a comparison.

Less than could be tested for by doing a simple subtraction and looking at the sign bit. How would you do this? Put one number through a line of NOT gates, then feed it into a CPA (Carry Propagating Adder) with a '1' set on the carry input. The CPA used will be, with almost 100% certainty, be one with a prefix network, giving a time complexity of (lg n).

So both of these operations are equally fast, but here's the fun part:

CPUs are CLOCKED DIGITAL CIRCUITS and these operations, sometimes even including multiplication, are all done in ONE CLOCK CYCLE

Name: Anonymous 2012-04-13 12:29

>>49,50
Unless you're Notch.

Name: Anonymous 2012-04-13 14:03

>>35
Go scrub a midget.

Name: bampu pantsu 2012-05-29 4:20

bampu pantsu

Don't change these.
Name: Email:
Entire Thread Thread List