Wie ermittelt man, ob Speicher ausgerichtet ist?
Ich bin neu in der Optimierung von code mit SSE/SSE2 Anweisungen und bis jetzt habe ich nicht bekommen, sehr weit. Meines Wissens eine gemeinsame SSE-optimierte Funktion würde wie folgt Aussehen:
void sse_func(const float* const ptr, int len){
if( ptr is aligned )
{
for( ... ){
//unroll loop by 4 or 2 elements
}
for( ....){
//handle the rest
//(non-optimized code)
}
} else {
for( ....){
//regular C code to handle non-aligned memory
}
}
}
Jedoch, wie kann ich korrekt bestimmen, wenn der Speicher ptr
Punkte ausgerichtet ist, wie z.B. 16 Bytes? Ich denke, dass ich noch die regulären C-code-Pfad für den nicht ausgerichteten Speicher, da ich nicht sicherstellen, dass jede Erinnerung an diese Funktion übergeben wird, ausgerichtet werden. Und mit der systeminterne Funktionen zum laden von Daten aus nicht ausgerichteten Speicher, in den SSE-Registern, zu sein scheint schrecklich langsam (Noch langsamer als die regulären C-code).
Danke im Voraus...
InformationsquelleAutor der Frage user229898 | 2009-12-13
Du musst angemeldet sein, um einen Kommentar abzugeben.
EDIT: casting zu
long
ist ein billiger Weg, sich selbst zu schützen gegen die wahrscheinlichste Möglichkeit von int und Zeiger werden in verschiedenen Größen heutzutage.Wie bereits in den Kommentaren unten, es gibt bessere Lösungen, wenn Sie bereit sind, um einen header...
Einen Zeiger
p
ist ausgerichtet auf eine 16-byte-Grenze iff((unsigned long)p & 15) == 0
.InformationsquelleAutor der Antwort Pascal Cuoq
Den cast zu
void *
(oder, equivalenty,char *
) ist notwendig, da der standard garantiert nur eine invertierbar Umstellung aufuintptr_t
fürvoid *
.Wenn Sie möchten, geben Sie Sicherheit, erwägen Sie die Verwendung einer inline-Funktion:
und hoffe für compiler-Optimierungen, wenn
byte_count
ist eine Compilezeit-Konstante.Warum brauchen wir, um zu konvertieren
void *
?Die Sprache C erlaubt unterschiedliche Darstellungen für die verschiedenen Mauszeiger-Typen, zB könnten Sie eine 64-bit -
void *
Typ (der gesamte Adressraum) und einen 32-bit -foo *
Typ (a-segment).Die Umwandlung
foo *
->void *
könnte beinhalten eine tatsächliche Berechnung, z.B. ein offset Hinzugefügt wird. Der standard überlässt die Umsetzung was passiert, wenn die Umwandlung (beliebigen) Zeiger auf Integer-zahlen, aber ich vermute, dass es oft umgesetzt wie eine noop.Für eine solche Umsetzung
foo *
->uintptr_t
->foo *
funktionieren würde, aberfoo *
->uintptr_t
->void *
undvoid *
->uintptr_t
->foo *
würde nicht. Die Ausrichtung Berechnung würde auch nicht zuverlässig arbeiten, weil Sie nur prüfen Sie die Ausrichtung relativ zu den segment-offset, die möglicherweise oder möglicherweise nicht, was Sie wollen.Fazit: verwenden Sie Immer
void *
zu bekommen Implementierung-unabhängige Verhalten.InformationsquelleAutor der Antwort Christoph
Anderen Antworten deuten auf eine UND den Betrieb mit niedrigen bits festgelegt, und im Vergleich zu null.
Aber ein mehr straight-forward-test wäre eine MOD mit der gewünschten Ausrichtung Wert, und vergleichen Sie diese mit null.
InformationsquelleAutor der Antwort Craig McQueen
Eine Funktion, mit der Vorlage, wie
könnten Sie, prüfen Sie die Ausrichtung zur Laufzeit durch Aufruf etwas wie
Überprüfen, dass schlechte Ausrichtungen scheitern, könnten Sie tun,
InformationsquelleAutor der Antwort rubicks
Kann Sie nur " und " der ptr mit 0x03 (ausgerichtet auf 4s), 0x07 (ausgerichtet auf 8s) oder 0x0f (ausgerichtet auf 16s) zu sehen, wenn eine der niedrigsten bits sind gesetzt?
InformationsquelleAutor der Antwort Paul Tomblin
Dies ist im Grunde das, was ich verwende. Durch die integer-eine Vorlage, die ich es ist sicher, erweiterten compile-Zeit, also werde ich nicht am Ende mit eine langsame modulo-operation was ich Tue.
Ich gerne überprüfen ob meine Eingabe, und somit den compile time assertion. Wenn die Ausrichtung mit dem Wert falsch ist, gut dann ist es nicht kompilieren...
Um zu sehen, was Los ist, können Sie diese verwenden:
InformationsquelleAutor der Antwort atlaste
Wie etwa:
InformationsquelleAutor der Antwort Ramana