|
|
This thread is locked; no one can reply to it.
|
1
2
|
| std::vector, Where Have You Been All My Life? |
|
Charles256
Member #8,370
February 2007
|
I remember learning about vectors in my beginning c++ programming class. Long time ago,but they are awsome. Been developing in PHP for five years and I must admit, that was awsome too. I love them both. :-D |
|
Jakub Wasilewski
Member #3,653
June 2003
|
Quote: std::copy(mystrlist.begin(), mystrlist.end(), ostream_iterator<string>(cout, "item seperator")); Oh my God. I think I'd prefer to write it out as a for loop. You know, so that my eyes don't bleed :-). --------------------------- |
|
ImLeftFooted
Member #3,935
October 2003
|
Quote: You know, so that my eyes don't bleed :-). Yes but its fukcing blazing fast. That statement will be faster then writing out the for loop yourself! For the kind of efficiency, thats the cleanest code I've ever seen. C++ was meant to be fast and elegant, not noobish. Don't mistake the two. |
|
CGamesPlay
Member #2,559
July 2002
|
Quote: That statement will be faster then writing out the for loop yourself! Err... prove it. -- Ryan Patterson - <http://cgamesplay.com/> |
|
Carrus85
Member #2,633
August 2002
|
Oh, and lets not forget the opposite operation: vector<string> tokens; copy(istream_iterator<string>(cin), istream_iterator<string>(), back_inserter(tokens));
|
|
ImLeftFooted
Member #3,935
October 2003
|
CGamesPlay said: Err... prove it. A compiler can unroll the loop, as well as a plethora of other tricks. |
|
Jakub Wasilewski
Member #3,653
June 2003
|
Quote: A compiler can unroll the loop. Really? The compiler has no prior knowledge of the number of elements in mystrlist, so it can't unroll it fully. It can partially unroll it (i.e., execute it in blocks of 8 iterations or whatever using the Duff's device for example), but that can be just as easily done to any for loop. I'm not saying it won't be faster - maybe it will be. But it's still butt ugly, and I'm not convinced it actually does provide a benefit. Anyway, the point is moot in that case, because the majority of the time will be spent on output to cout. --------------------------- |
|
HoHo
Member #4,534
April 2004
|
Quote: Err... prove it.
One sample output wit g++ -O2:Total time to copy 10000000 ints from one vector to other 100 times: Total time to copy 10000000 ints from one vector to other 100 times: std::copy: 2830000 regular loop: 30390000 Satisfied? Using cout would have been pointless as its overhead would have been way too high for measuring the actual looping process [edit] Total time to copy 100000 ints from one vector to other 10000 times: std::copy: 320000 regular loop: 29170000 -O2 Total time to copy 100000 ints from one vector to other 10000 times: std::copy: 350000 regular loop: 490000
__________ |
|
CGamesPlay
Member #2,559
July 2002
|
Use iterators
cgames@ryan ~ $ g++ test.cpp -O3 -funroll-loops cgames@ryan ~ $ ./a.out Total time to copy 100000 ints from one vector to other 10000 times: std::copy: 690000 regular loop: 970000 iterator loop: 900000 Okay, so it's faster, and by a fair margin, but why? [edit] -- Ryan Patterson - <http://cgamesplay.com/> |
|
Jakub Wasilewski
Member #3,653
June 2003
|
Here is the loop I had in mind: for(int i=0;i<LOOPS;i++) for(it1 = intvec1.begin(), it2 = intvec3.begin(); it1 != intvec1.end(); it1++, it2++) (*it2) = (*it1); With regular loop changed to that, and -O2: Quote:
Total time to copy 10000000 ints from one vector to other 1000 times: Negligible 1.5% difference. Anyway, I was just playing - if there is a good way to use <algorithm> by all means, you should use it. But it's not all that important if the loop version will be more readable. This is not so in the case of std::copy, which is very straight-forward. But in the case of algorithms that require you to define a function (which will often be used only this once), it's not worth the hassle. Not unless we get lambda functions in C++. --------------------------- |
|
CGamesPlay
Member #2,559
July 2002
|
Here's a silly.
$ g++ test.cpp -O3 -funroll-loops && power ./a.out Total time to copy 10000 ints from one list to other 100000 times: std::copy: 7220000 iterator loop: 6930000 <hypothesis>It seems copy is doing a memcpy internally, overridden for vectors. When it can't do so and must use a generic copy function, the overhead of the method pointers causes it to be slower.</hypothesis> -- Ryan Patterson - <http://cgamesplay.com/> |
|
HoHo
Member #4,534
April 2004
|
Put all together and ran on my Core2 at 32bit: #g++ std_copy.cpp -O3 -funroll-loops && ./a.out Total time to copy 100000 ints from one vector to other 10000 times: std::copy: 390000 regular loop: 550000 iterator loop: 580000 Jakub's loop: 560000 I ran it several times and there weren't much changes. Different CPU's might give different results. __________ |
|
CGamesPlay
Member #2,559
July 2002
|
You have a fast machine, HoHo I'm running a Core Duo at 3.0 GHz with I think 4 MB cache between the cores. -- Ryan Patterson - <http://cgamesplay.com/> |
|
HoHo
Member #4,534
April 2004
|
Core2Duo e4300@2.93GHz at the moment. That means 2M L2 shared between two cores and ~62% OC. Could go higher when I could somehow give it more than default voltage Total time to copy 10000 ints from one list to other 100000 times: std::copy: 1480000 iterator loop: 1520000 When I changed list to vector then iterator loop actually got faster than std::copy Total time to copy 10000 ints from one vector to other 100000 times: std::copy: 480000 iterator loop: 430000 Well, all I can say is when in doubt, benchmark __________ |
|
ImLeftFooted
Member #3,935
October 2003
|
Yeah lists are bloated and are almost completely useless because of it. They're more useful for academic purposes then anything else. |
|
anonymous
Member #8025
November 2006
|
Quote: Yeah lists are bloated and are almost completely useless because of it. They're more useful for academic purposes then anything else.
Hm, lists have faster insertions that vectors. You can remove elements in constant time. If you sort a list of MyClass (using list::sort), it could seriously outperform std::sort on vector, because it doesn't need to copy actual data, just rearrange the pointers. Each STL container has its strenghts and weaknesses. Sometimes it might even be more efficient to use one type for one task, and then copy the data to a different container to do something else with the data. For example, std::set is blazing fast to get you unique, sorted data. If you needed a lot of random access on the data later, you might copy it to a vector before continuing. (Benchmark, of course.) *** By the way, they say that the container's "native" methods could be faster than the equivalent std::algorithm (optimized for this particular container). Anybody care to benchmark operator = ? |
|
HoHo
Member #4,534
April 2004
|
Quote: Hm, lists have faster insertions that vectors You can remove elements in constant time If the vector doesn't need to be sorted you can add and remove stuff from there in constant time too. Quote: If you sort a list of MyClass (using list::sort), it could seriously outperform std::sort on vector, because it doesn't need to copy actual data That depends on how you use it. If you have enormous list then iterating it over and over again will probably take more time than with vectors (need benchmarks!). If you don't keep pointers in the container and the elements are big then lists may win. Quote: Each STL container has its strenghts and weaknesses I agree. Though if you can alter your design just a little you may find that vectors perform better than lists for most things. Also in some cases deque may be a bit better than vector. Last time I used lists was about three years ago in uni when we were asked to write a list class __________ |
|
anonymous
Member #8025
November 2006
|
Quote: If the vector doesn't need to be sorted you can add and remove stuff from there in constant time too. That's a big "if". And a vector may get copied using push_back(). And if you wanted to keep the container sorted, a multiset would probably be fastest. Quote:
Quote: If you sort a list of MyClass (using list::sort), it could seriously outperform std::sort on vector, because it doesn't need to copy actual data That depends on how you use it. If you have enormous list then iterating it over and over again will probably take more time than with vectors (need benchmarks!). If you don't keep pointers in the container and the elements are big then lists may win. List can win clearly, if the copy constructor is expensive. For example when sorting std::strings. Quote:
Quote: Each STL container has its strenghts and weaknesses I agree. Though if you can alter your design just a little you may find that vectors perform better than lists for most things. Also in some cases deque may be a bit better than vector. Last time I used lists was about three years ago in uni when we were asked to write a list class Yes, a vector is a most general use container, because very often random access is what you need (replacement to single array). However, it is impossible to design a container that works remarkably well for all purposes, because you need a different structure for each purpose. Knowing the tools is good, also STL is designed in a way, that it is relatively easy to switch the container you are using and to move data to a different container. I can also see how implementing your own list deters you from using std::list |
|
Carrus85
Member #2,633
August 2002
|
Quote:
Quote: If the vector doesn't need to be sorted you can add and remove stuff from there in constant time too. That's a big "if". And a vector may get copied using push_back(). And if you wanted to keep the container sorted, a multiset would probably be fastest. Not if it is a compliant STL implementation and you have already reserved enough slots for your data set (two conditions which are easily satisfied). Quote:
Quote:
Quote: If you sort a list of MyClass (using list::sort), it could seriously outperform std::sort on vector, because it doesn't need to copy actual data That depends on how you use it. If you have enormous list then iterating it over and over again will probably take more time than with vectors (need benchmarks!). If you don't keep pointers in the container and the elements are big then lists may win. List can win clearly, if the copy constructor is expensive. For example when sorting std::strings.
Of course, vectors can easily win if you don't sort the actual array contents (you generate an sorted index->actual index mapping that happens to return items in sorted order). Completely avoids copy constructor overhead. Granted, this is not what is done in any STL container as far as I know, but it is possible to sort a vector-like container with zero data copies of the actual container data this way... (it would be interesting though to have an STL wrapper object that does just this for all random access data types; call it something like sorted_wrapper.)
|
|
anonymous
Member #8025
November 2006
|
Quote: Of course, vectors can easily win if you don't sort the actual array contents (you generate an sorted index->actual index mapping that happens to return items in sorted order). Completely avoids copy constructor overhead. Granted, this is not what is done in any STL container as far as I know, but it is possible to sort a vector-like container with zero data copies of the actual container data this way... (it would be interesting though to have an STL wrapper object that does just this for all random access data types; call it something like sorted_wrapper.)
For copy-expensive objects, you can sort a vector of pointers to the object. Although it is still questionable if it is worth the effort if list can do this without any extra work. Your idea is interesting, but wouldn't it produce massive overhead - no less than a list? Also, after sorting, wouldn't you still need to do the copying in one go (adds at least O(N) and seems tricky to do in-place)? Anyway, I'm not saying list is better than vector per se (or the other way round). But a simple contiguous block of memory just doesn't suit well for all kinds of manipulations. Nor does any other data structure. So you have to make choices. Finally, here's a link to compare the effectiveness of some operations with different containers. (Keeping in mind that O(N) can mean very different things with different containers.) The rest of the site is interesting reading too! |
|
Tobias Dammers
Member #2,604
August 2002
|
...and after all, keep in mind that STL containers are designed to use the same interface wherever possible, so if all is well, changing the container type for a given application later on shouldn't be too much of a problem. Just profile them against each other and see what's faster. --- |
|
|
1
2
|