Hallo Steffen
Hier die Ergebnisser der Zeitmessungen:
Iterieren Vector:
VS.net: 0,92ms
VS 6: 0,84ms
VS 2005: 0,91ms
Borland: 0,95ms
GNU: 1,40ms
Iterieren Array []:
VS.net: 1,11ms
VS 6: 1,00ms
VS 2005: 1,00ms
Borland: 1,02ms
GNU: 0,99ms
Iterieren Array *:
VS.net: 1,08ms
VS 6: 1,00ms
VS 2005: 0,97ms
Borland: 1,07ms
GNU: 0,98ms
Man sieht ja recht deutlich, dass die beiden Messungen mit dem
Array nahezu identische Ergebnisse liefern, während der Vector
(abgesehen vom GNU-Compiler) immer langsamer ist, was gegen
die Theorie spricht, dass der []-Operator eine Operation mehr
durchführen muss, oder?
Ich denke mal, das ist ausschliesslich ein
Problem der Speicherverwaltung. Alle Operationen
„drum herum“ spielen hier kaum eine Rolle, ausser
dass u.U. bei ein geringer Overhead exis-
tieren kann. geringe Laufzeitunterscheide dürften
reiner Zufall sein und sich ggf. bei verschiedenen
Läufen ändern. Möglicherweise kannst Du noch ein
paar (lokale) Berechnungen einflechten, ohne dass
sich die Laufzeit ändert.
Ich hab mal die Quell-Fragmente hergenommen,
die Blockgröße erhöht und ein paar Tests gemacht.
Je nach Compiler wird statistisch eher das
eine oder eher das andere „etwas“ schneller
sein. Signifikant ist das wahrscheinlich nicht.
Das Alignment spielt offenbar keine Rolle, alle
Compiler machen ein „padding“ des char-Members
auf 32bit.
Beispiel:
groesse = 10_000_000 (==> 2 x 160MB data blocks)
Visual C++/6 SP5 -Oxt
VECTOR : 406994181 cpu cycles,
ARRAY : 402805987 cpu cycles,
POINTER: 401981090 cpu cycles
gcc 3.4.1, -O3
VECTOR : 404375218 cpu cycles,
ARRAY : 408711841 cpu cycles,
POINTER: 431653670 cpu cycles
gcc 4.0.2 -O3
VECTOR : 442514272 cpu cycles,
ARRAY : 432433397 cpu cycles,
POINTER: 404922653 cpu cycles
Die „Zeitmessung“ habe ich mit dem
‚time stamp counter‘ des Prozessors
vorgenommen, er gibt die Anzahl der
‚raw‘-Zyklen an (CPU: Athlon-64/3400)
Hier der Quelltext, den ich verwendet habe:
#include "rdtsc.h" // for tsc\_ticks()
#include
#include
#include
class MyClass {
public:
int size, x, y;
unsigned char gw;
MyClass() {
x = (rand() % 1024);
y = (rand() % 768);
size = (rand() % 400);
gw = (rand() % 255);
}
};
int proc(QWORD& ve\_end, QWORD& ar\_end, QWORD& pt\_end)
{
unsigned long i, groesse = 10000000;
MyClass einfuege\_objekt;
std::vector t\_vector;
std::vector::iterator iter\_t\_vector;
MyClass \*t\_arr = new MyClass[groesse];
MyClass \*Pointer = t\_arr;
QWORD start; // QWORD is "unsigned long long" or "\_\_int64"
t\_vector.reserve(groesse);
for (i=0; isize = 100;
}
ve\_end = tsc\_ticks() - start;
// - - - - - - do array test
start = tsc\_ticks();
for (i=0; isize = 100;
}
pt\_end = tsc\_ticks() - start;
// make sure the loop won't be 'optimized away':
return Pointer-\>size + t\_arr[0].size + iter\_t\_vector-\>size;
}
int main()
{
QWORD ve\_end, ar\_end, pt\_end;
proc(ve\_end, ar\_end, pt\_end);
printf( "\nsizeof(MyClass): %i bytes \n\n"
"\nVECTOR : %8u cycles,"
"\nARRAY : %8u cycles,"
"\nPOINTER: %8u cycles\n",
sizeof(MyClass),
(long)ve\_end, (long)ar\_end, (long)pt\_end);
return 0;
}
Die Funktion tsc_ticks() sähe dann so aus:
QWORD tsc\_ticks()
{
#ifdef \_MSC\_VER
// disable "no return value" warning
#pragma warning( disable : 4035 )
\_asm xor eax, eax
\_asm xor edx, edx
\_asm rdtsc // \_asm \_emit 0x0f // \_asm \_emit 0x31
#else
// standard gnu inline assembly version
\_\_asm\_\_ (
"xorl %eax, %eax\n"
"xorl %edx, %edx\n"
"rdtsc");
#endif
}
Grüße
CMБ