2010-11-24 3 views
3

Kontext:C++: Vergleich Leistung von Zeigern an verschiedenen Stellen in einem char-Array zeigt (Versuch Ausrichtung zu lernen)

char buffer[99]; int* ptr_int=(int*)(buffer+n); 

Dann habe ich einige Zeit Operationen an * ptr_int und messen Ausführung zeitraubend Fenster mit .h/QueryPerformanceCounter.

Verwirrung: Für Werte von n: 0 bis 4, ist die Ausführungszeit etwa 12 Sekunden Für Werte von n: 5,6,7 Ausführungszeit etwa 20 Sekunden betragen Für Wert von n: 32,33 Ausführungszeit ist wieder etwa 12 Sekunden.

Dies kann aufgrund der Ausrichtung sein, aber kann jemand bitte erklären, wie genau?

Pentium Dual-Core T2410/winxp/g ++ 3.4.2 (mingw-special)

bearbeiten ich versuche nicht mithilfe bessere Ansätze, um die Ausrichtung Problem zu vermeiden, bin ich stattdessen versuchen, zu finden, warum ich int* ptr_int=(int*)(buffer+5);

Kein Problem mit plötzlich mit Ausrichtungsproblem haben: int* ptr_int=(int*)(buffer+3); OR int* ptr_int=(int*)(buffer+33);

+0

Das wird auf einigen Architekturen nicht funktionieren. Sie werden Hardwarefehler bekommen. Sie scheinen Glück zu haben, dass entweder Ihr Compiler kompensiert oder Ihre Hardware in Ordnung ist. Die Ausrichtung muss der Größe des Objekts entsprechen. –

+0

Wenn Sie Ausrichtungsprobleme ausschließen möchten, messen Sie die Zeiten für den Zugriff auf Zeichenelemente des Arrays (oder verwenden Sie ein int-Array) – Amnon

+0

Schauen Sie sich auch die Adresse von 'Puffer' an und sehen Sie, wie es ausgerichtet ist. – antsyawn

Antwort

1

auf modernen CPUs, Daten richtig ausgerichtet muss, sonst Es wird höllisch zu bezahlen sein. Eine 32-Bit-Ganzzahl muss um 4 Bytes ausgerichtet werden, andernfalls muss die CPU intern zwei Ganzzahlen lesen und die Dinge entsprechend verschieben. Einige CPUs stürzen tatsächlich ab, wenn Sie versuchen, eine nicht ausgerichtete Ganzzahl zu lesen.

Ebenso ist ein 128-Bit-__vector4 von 16 Byte ausgerichtet werden muss, usw.

By the way, gibt es andere Faktoren, die ins Spiel kommen, wie die Daten-Cache-Zeile, so das erste Mal, wenn Sie Zugang eine neue Cache-Zeile, wird es eine große Strafe geben - nachfolgende Lesevorgänge werden viel schneller sein.

0

Eine ausführliche Erklärung dieser und anderer Speicherprobleme finden Sie in Ulrich Dreppers exzellentem Artikel "What Every Programmer Should Know About Memory", zusammen mit Beispielbenchmarks, die Sie selbst ausführen können.

0

Sehr wahrscheinlich, wie die anderen sagten, dies ist ein Alignment-Problem. Jetzt gibt es ein paar Möglichkeiten, wie Sie es beheben und testen können.

Am einfachsten ist es, malloc oder new zu verwenden, um den Puffer auf dem Heap zuzuordnen. Malloc garantiert, dass der zurückgegebene Zeiger für die Ausrichtung des größten nativen Datentyps geeignet ist. Auf Intel 64-Bit-Chips bedeutet dies, dass es auf ein 128-Bit-Double ausgerichtet ist.

char * buffer = malloc(n * sizeof(int)); 

int * at = (int*)buffer + ndx; 

Es sieht aus wie Ihre ursprünglichen +n auch falsch war. Die Art und Weise, wie Sie das gemacht haben, bestand darin, das char ptr um 1 Byte statt um das int ptr um 4 Bytes zu versetzen. Dies könnte auch die Verlangsamung erklären, wenn Sie die ganzen Zahlen kopieren. Dies liegt daran, dass Sie unbeabsichtigt Integer verwendet haben, die den gleichen Speicherort überlappen.

Wenn Sie die Stapelzuweisung verwenden müssen, und es kommt, können Sie das auch ausrichten.Es gibt eine Boost-Funktion, das dies tut auch ich glaube,

char cbuffer[1024+sizeof(int)]; 
int * ibuffer = (cbuffer/sizeof(int) + 1) * sizeof(int); 

Dann ibuffer wird integer ausgerichtet werden. Der tatsächliche Zeigerwert ist möglicherweise nicht der gleiche wie für cbuffer, aber in einigen Fällen kann es sein (hängt von dem Stapel zum Zeitpunkt des Anrufs ab). Die zweite Zeile ist eine einfache Mathematik auf dem Zeiger, um sicherzustellen, dass es ein Vielfaches von sizeof (int) ist, was bedeutet, dass es int ausgerichtet ist.

neu: Kann jemand bestätigen, ob new char[x] auch Ausrichtung garantiert, wie malloc tut?