Re: C++ programmer and assembly
On Apr 20, 12:32 am, Francis Glassborow
<franc...@robinton.demon.co.uk> wrote:
[snip]
You have managed to entirely miss the point.
Missing someone's point is easily done in particular on Usenet :-)
Given the iterator,
insertion into a list is O(1) well it would be if it were not that you
have to find and fetch the node before and after the insertion point and
that can involve paging virtual memory. Inserting to a vector is O(n)
but for small enough collections all whole vector fits in level 0 cache
and the actual operations are very fast.
Now I think I get it.
The fact that a vector's elements are held in contiguous memory
can be far more significant than the cost of copying the elements to
create space for a new one in the middle of a sequence.
Note that I do not need to know about assembler programming to
understand this but I do need to know something about the way modern
machines handle memory requirements and the properties of different
containers.
Anyway, I _had_ to check it. I wrote a simple test program presented
below. I've assumed insert/erase at the beginning of a sequence fair
enough competition.
A macro LIST is used to determine at compile time which sequence
container to test. A call to 'spare()' function which allocates some
heap memory is made before every insertion in order to ensure list
nodes are not too close to each other. The sequence is initialized
with a dozen of elements before the iterations. The total number of
iterations is given on the command line. Upon every iteration a call
to 'rand()' is made in order to judge insert() or erase() should take
place.
$ cat list-myth.cpp
#ifdef LIST
#include <list>
typedef std::list< int > sequence;
#else
#include <vector>
typedef std::vector< int > sequence;
#endif
#include <iostream>
#include <ostream>
#include <cstdlib>
inline void
spare()
{
new char[4096];
}
int
main(int argc, char* argv[])
{
sequence seq;
for (int i = 0; i < 12; ++i)
{
seq.push_back(i);
spare();
}
char const* progname = argv[0];
if (argc != 2)
{
std::cerr << "usage: " << progname << " COUNT" << std::endl;
return 1;
}
size_t count = strtoul(argv[1], NULL, 0);
if (count == 0)
{
std::cerr << progname << ": COUNT should be positive integer"
<< std::endl;
return 1;
}
for (size_t i = 0; i < count; ++i)
{
int rnd = rand();
if ((rnd & 1) || seq.empty())
{
spare();
seq.insert(seq.begin(), rnd);
}
else
{
seq.erase(seq.begin());
}
}
}
$ make
g++ list-myth.cpp -DLIST -o list.exe -Wall -O3
g++ list-myth.cpp -DVECTOR -o vector.exe -Wall -O3
$ make test
/bin/sh.exe -c "time ./list.exe 2000"
real 0m0.031s
user 0m0.015s
sys 0m0.015s
/bin/sh.exe -c "time ./vector.exe 2000"
real 0m0.047s
user 0m0.015s
sys 0m0.030s
$
I've repeated the test a fair amount of times. The timings I get are
comparable.
I've tried to change COUNT given on command line, to increase the
number of bytes 'spare()' function allocates, to increase the initial
number of elements in the sequence and, finally, all of it at once,
but with no effect--timings were still comparable.
I've tested this on two different machines: 1.8 GHz AMD Athlon running
Windows (with mingw g++-3.3.1) and 733 MHz Intel PIII running Debian
GNU/Linux (with g++-3.3.5).
Yes, the comparable timings are in fact counter-intuitive to someone
not taking CPU caches into account (for example, me former on this
thread), but still I cannot see std::vector outperforming std::list in
speed by "an order of magnitude" :-)
Am I missing something this time too?
Here is my Makefile for completeness:
$ cat Makefile
ifdef WINDIR
exe = .exe
endif
targets = list$(exe) vector$(exe)
all: $(targets)
clean:
rm -f $(targets)
ifndef COUNT
COUNT = 2000
endif
test: all
$(SHELL) -c "time ./list$(exe) $(COUNT)"
$(SHELL) -c "time ./vector$(exe) $(COUNT)"
..PHONY: all clean test
cflags = -Wall -O3 $(CFLAGS)
list$(exe): list-myth.cpp Makefile
g++ $< -DLIST -o $@ $(cflags)
vector$(exe): list-myth.cpp Makefile
g++ $< -DVECTOR -o $@ $(cflags)
--
Regards,
Alex Shulgin
PS: I sincerely hope I am not abusing your and other patience :-)
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]