Leider max Ausrichtung gewährleistet ist viel härter als es sein sollte, und es gibt keine Garantie Lösungen AFAIK. Vom GotW Blog (Fast Pimpl article):
union max_align {
short dummy0;
long dummy1;
double dummy2;
long double dummy3;
void* dummy4;
/*...and pointers to functions, pointers to
member functions, pointers to member data,
pointers to classes, eye of newt, ...*/
};
union {
max_align m;
char x_[sizeofx];
};
Dies nicht als vollständig tragbare garantiert ist, aber es ist nah genug, weil es nur wenige oder keine Systeme, auf denen dies nicht funktioniert in der Praxis als erwartet.
Das ist über den nächsten "Hack", den ich dafür kenne.
Es gibt einen anderen Ansatz, den ich persönlich für super schnelle Zuweisung verwendet habe. Beachten Sie, dass es böse ist, aber ich arbeite in Raytracing-Bereichen, in denen Geschwindigkeit einer der größten Qualitätsmaßstäbe ist und wir den Code täglich grafisch darstellen. Dies beinhaltet die Verwendung eines Heap-Allokators mit vor-allokiertem Speicher, der wie der lokale Stapel funktioniert (erhöht nur einen Zeiger auf die Zuweisung und dekrementiert einen um die Freigabe).
Ich verwende es für Pimpls besonders. Es reicht jedoch nicht, den Allokator zu haben. Damit ein solcher Allokator funktionieren kann, müssen wir annehmen, dass Speicher für eine Klasse, Foo, in einem Konstruktor zugewiesen wird, der gleiche Speicher ebenfalls nur im Destruktor freigegeben wird und dass Foo selbst auf dem Stapel erstellt wird. Um es sicher zu machen, brauchte ich eine Funktion, um zu sehen, ob der "This" -Zeiger einer Klasse auf dem lokalen Stack ist, um festzustellen, ob wir unseren super schnellen haufenbasierten Stack Allocator verwenden können.Dazu mussten wir OS-spezifische Lösungen recherchieren: Ich verwendete TIBs und 10 für Win32/Win64, und meine Mitarbeiter fanden Lösungen für Linux und Mac OS X.
Das Ergebnis, nach einer Woche der Erforschung von OS-spezifischen Methoden zum Erkennen von Stack-Bereich, Ausrichtung Anforderungen, und eine Menge von Tests und Profilerstellung, war ein Allokator, der Speicher in 4 Taktzyklen nach unseren Tick Counter Benchmarks im Gegensatz zu etwa 400 Zyklen für Malloc/Operator neu zuordnen könnte (unser Test beteiligt Threadkonflikt, so dass malloc in Singlethread-Fällen wahrscheinlich ein wenig schneller ist, vielleicht ein paar hundert Zyklen). Wir fügten einen Pro-Thread-Heap-Stack hinzu und erkannten, welcher Thread verwendet wurde, was die Zeit auf ungefähr 12 Zyklen erhöhte, obwohl der Client den Thread-Allokator verfolgen kann, um die 4-Zyklen-Zuordnungen zu erhalten. Es löschte Speicherzuweisung basierte Hotspots von der Karte.
Während Sie nicht durch all diese Schwierigkeiten gehen müssen, könnte das Schreiben eines schnellen Allokators einfacher und allgemeiner anwendbar sein (z. B. die Menge des zuzuweisenden Speicherplatzes zur Laufzeit bestimmen) als etwas wie max_align
Hier. max_align
ist einfach genug zu verwenden, aber wenn Sie Geschwindigkeit für Speicherzuweisungen sind (und vorausgesetzt, Sie haben bereits Ihren Code profiliert und gefunden Hotspots in malloc/free/operator new/delete mit wichtigen Mitwirkenden in Code haben Sie die Kontrolle über) Wenn Sie Ihren eigenen Zuordner schreiben, kann das den Unterschied ausmachen.
portable in welcher Hinsicht genau sein? zu jedem Compiler? zu jedem Betriebssystem? zu jeder Architektur? –
Nur portabel wie in "garantiert vom C++ Standard zu arbeiten". Natürlich könnte ich mich leicht auf meine eigenen Kenntnisse der Zielarchitektur verlassen und die maximale Ausrichtung fest codieren, aber es wäre schön, wenn die Sprache selbst die Werkzeuge zur Verfügung stellen würde, um dies zu beantworten. – jalf
Beachten Sie, dass der Template-Parameter 'Align' von' std :: aligned_storage 'ein Standardargument von" default-alignment "hat, das definiert ist als" Der Wert von default-alignment soll die strengste Alignment-Anforderung für jedes C++ Objekt sein Typ, dessen Größe nicht größer als "Len" ist. " Ich weiß nicht, ob SSE-Typen als "C++ - Objekttypen" betrachtet werden, und die VC10-Standardbibliothek hat nicht das Standardargument, daher weiß ich nicht, was der beabsichtigte Wert ist (ich habe keine andere Standardbibliothek Implementierungen auf dieser Maschine). –