Wenn ich ein Spiel habe, das eine 3D-Welt hat und die Welt ziemlich groß ist, also in Stücke aufgeteilt werden muss, gibt es einen großen Leistungsvorteil, wenn überhaupt, 128-Byte-Stücke über, sagen wir 150-Byte-Stücken zu haben? Offensichtlich sind die Objekte in den Chunks immer noch eine ganze Anzahl von Bytes groß.
dh ist chunks[128][128][128] schneller als chunks[150][150][150] oder chunks[112][112][112]? Gibt es im Nachhinein weitere Nebeneffekte wie übermäßige RAM-Verschwendung? Gibt es weitere Faktoren, die berücksichtigt werden sollten?
Ich sehe nur, dass es eine Konvention ist, alles in Variablen und Arrays mit Größen zu speichern, die Potenzen von 2 sind, aber ich bin mir nicht sicher, ob es einen Vorteil hat und ob es besser sein könnte, mehr menschliche Zahlen wie 100 oder 150 zu verwenden .
Ich denke, es hängt von der Art des Arrays ab. Nicht-Byte-Typen erfordern möglicherweise eine Speicherausrichtung.
– Vulkanino
1. März 2012 um 11:43 Uhr
In diesem Fall ist jedes Objekt im Chunk 16 Bit oder vielleicht eine andere Potenz von 2 groß (definitiv eine ganze Zahl von Bytes). Ich möchte wissen, ob 150 16-Bit-Objekte langsamer sind als 128 (beachten Sie, dass es immer noch genauso viele Objekte gibt, sie würden nur in mehr Teile aufgeteilt).
– Greg
1. März 2012 um 11:45 Uhr
Stellen Sie sich vor, Sie haben 1000 Personen zu transportieren und Sie haben Busse mit einer Kapazität für 50 Personen. Was ist deiner Meinung nach besser? Menschen in Gruppen von 50 gruppieren oder sie in Gruppen von 72 (oder 38 oder was auch immer) gruppieren und Gruppen aufteilen, bevor die Busse gefüllt werden?
– pmg
1. März 2012 um 11:53 Uhr
Stellen Sie sich vor, die Leute haben verschiedenfarbige Hüte. Wenn Sie sie nach einer anderen Zahl als der Buskapazität gruppieren, hat jeder Bus Menschen mit andersfarbigen Hüten. Die Verwendung von Zweierpotenzen für Array-Dimensionen verbessert die Wahrscheinlichkeit, dass jede Array-Gruppe (von index bis kurz davor index + 1) belegt einen Teil des Speichers, auf den als Ganzes zugegriffen werden kann.
– pmg
1. März 2012 um 12:03 Uhr
Als Wort der Warnung: Die Verwendung von Zweierpotenzen kann zu Super-Alignment-Konflikten führen. Siehe dies und das. Super-Ausrichtung (von Power-of-two-Schritten) kann die Leistung leicht um das Dreifache oder mehr verringern. Was Sie also durch den Handel gewinnen, multipliziert sich mit Schichten, kann leicht (um ein Vielfaches) durch Cache-Fehler und falsche Aliasing-Stalls verloren gehen.
– Mystisch
7. März 2012 um 6:39 Uhr
Mystisch
Die anderen Antworten sind in der Tat richtig, dass Daten in Zweierpotenz von der Verwendung von Verschiebungen über Multiplikationen profitieren.
Jedochda ist ein dunkle Seite zu Potenz-von-Zwei-Größendaten. Und es kann dich treffen, wenn du es am wenigsten erwartest.
Siehe diese beiden Fragen/Antworten:
Matrixmultiplikation: Kleiner Unterschied in der Matrixgröße, großer Unterschied im Timing
Warum sind elementweise Additionen in separaten Schleifen viel schneller als in einer kombinierten Schleife?
Wenn es sich bei Ihren Datensätzen um Zweierpotenzen handelt, ist es wahrscheinlicher, dass sie im Speicher super-ausgerichtet sind. (was bedeutet, dass ihre Adressen wahrscheinlich das gleiche Modulo über eine große Zweierpotenz haben werden.)
Dies mag zwar wünschenswert erscheinen, kann aber zu Folgendem führen:
False Aliasing Stalls (im zweiten Link oben erwähnt)
Wenn Sie die beiden oben verlinkten Fragen lesen, können Sie das sehen Ausrichtung kann eine Verlangsamung von mehr als 3x verursachen – was wahrscheinlich jeden Vorteil, den Sie durch die Verwendung von Verschiebungen im Gegensatz zu Multiplikationen erhalten, bei weitem überwiegen wird.
Wie bei allen Fragen zur Leistung müssen Sie also messen, messen, messen … Und darauf vorbereitet sein, dass alles passieren wird.
Sie erwähnen, dass Sie einen 3D-Raum darstellen – das ist genau die Art von Situation, die einen Zweierpotenz-Schrittspeicherzugriff aufweisen würde, der zu Verlangsamungen führen könnte.
+1, Cache-Fehlschläge sind viel schlimmer als die wenigen Zyklen, die Sie für die Multiplikation zum Adressieren aufwenden!
– Nils Pipenbrinck
7. März 2012 um 7:12 Uhr
Ja, ich war ziemlich überrascht, dass niemand die Ausrichtung als Nachteil erwähnte. Weder in den Antworten noch in den Kommentaren – vor allem angesichts der Aufmerksamkeit, die die Loop-Frage erhalten hat. Ich hätte das viel früher beantwortet, aber es war mitten in der Nacht in meiner Zeitzone, als es gefragt wurde. Also ich habe es bis jetzt nicht gesehen.
– Mystisch
7. März 2012 um 7:17 Uhr
Vielen Dank für die Erwähnung von Cache-Problemen! Nicht-Potenzen von zwei Größen können auch ohne Multiplikation erreicht werden. Eine Verschiebung und eine Addition geben Ihnen Blockgrößen wie 129 oder 255. Verschiebung und dann addieren / subtrahieren. Es lohnt sich jedoch zu überprüfen, ob Ihre Ziel-HW nicht in der Lage ist, so schnell zu multiplizieren wie zu verschieben und zu addieren / subtrahieren.
– Benjohn
6. September 2017 um 10:30 Uhr
Blagovest Buyukliev
Es ist nicht gerade “schneller”, sondern nutzt den verfügbaren Speicher besser aus, da die Hardware und das Betriebssystem den Speicher in Einheiten verwalten, die wahrscheinlich eine Zweierpotenz sind. Das Zuordnen von etwas, das kleiner als eine Zweierpotenz ist, führt normalerweise aufgrund von Ausrichtungsanforderungen zu einer Speicherverschwendung.
Wenn Sie sich eingehender mit Allokatoren und OS-Speichermanagern befassen, werden Sie feststellen, dass sie alles in Zweierpotenzgrößen verwalten. Ein Betriebssystem verwaltet den Speicher eines Prozesses normalerweise in Seiten, und eine Seitengröße beträgt heutzutage normalerweise 4096 Bytes. Wenn Sie also ein Stück mit 4000 Bytes zuweisen möchten, weist das Betriebssystem immer noch 4096 Bytes zu und die verbleibenden 96 Bytes werden verschwendet.
Wie viel RAM wird also ungefähr verschwendet, wenn 150 ^ 3 * 16 Bytes (6.750.000 Bytes) zugewiesen werden? Ist es eine erhebliche Menge?
– Greg
1. März 2012 um 11:52 Uhr
“und die restlichen 96 Bytes werden verschwendet.” Das ist ein sehr vereinfachte Ansicht. Die Speicherverwaltung erfolgt normalerweise in mehreren Schichten, und je nach Manager können diese 96 Bytes durchaus für andere Variablen verwendet werden.
– Adelphus
1. März 2012 um 12:10 Uhr
@adelphus: in der Tat ist es vereinfacht, ich wollte nur einen typischen konzeptionellen Fall beschreiben.
– Blagovest Buyukliev
1. März 2012 um 12:14 Uhr
Wenn Sie auf folgende Weise auf die Daten zugreifen:
chunks[150][150][150]
chucks[x][y][z] = 123;
Dann muss der Prozessor Multiplikationen durchführen (so etwas wie: z + 150 * (y + 150 * x) … ), um eine Adresse zu erhalten.
Wenn Sie Potenz-von-2-Konstanten verwenden, könnte der Compiler einige Optimierungen vornehmen und Verschiebungen anstelle von Multiplikationen verwenden. Die neue CPU macht Multiplikationen ziemlich schnell, daher ist der Effekt unbedeutend.
Die Verwendung einer großen Tabelle kann viele Cache-Miss verursachen. Ein kleinerer Tisch ist also wahrscheinlich schneller als ein größerer, selbst der größere hat Abmessungen in Zweierpotenz und der kleinere nicht.
Zweierpotenzen werden häufig in Software verwendet, weil es die Zahlenbasis ist, die Computer verwenden.
Beispielsweise weisen Betriebssysteme Speicher in Blockgrößen von Zweierpotenzen zu, die Cache-Größen im Prozessor sind Zweierpotenzen, Adressgrößen sind Zweierpotenzen und so weiter.
Operationen mit Potenzen von zwei Werten können ebenfalls optimiert werden – eine Multiplikation oder Division wird zu einer einfachen Bitverschiebung.
Grundsätzlich sicherzustellen, dass alles Zweierpotenzen verwendet könnte verbessern die Leistung Ihrer Software, aber normalerweise stellen ein Compiler und/oder ein Betriebssystem sicher, dass Ihre Daten effektiv genutzt werden, wenn Sie beliebige Größen verwenden.
Es kann schneller sein, es kann langsamer sein, es kann dieselbe Geschwindigkeit haben. Es wäre sehr schwierig, die richtige Antwort zu geben, indem man sich nur den Code ansieht. Also die Antwort: Messen, Code ändern, erneut messen. Wenn Ihr Code auf verschiedenen Computern ausgeführt werden muss, messen Sie ihn auf jedem.
Ich würde eher annehmen, dass die Zweierpotenz-Ausrichtung oft zu ernsthaften Problemen führt und dass die Verwendung von mehr Speicher als benötigt der Leistung nicht zugute kommt. Es hilft oft, viele Operationen mit einem kleinen Teil des Speichers durchzuführen, der in einen Cache passt, und dann zum nächsten Teil des Speichers zu wechseln. Der Zugriff auf aufeinanderfolgende Speicheradressen hilft oft. Aufrunden, damit Sie Vektoroperationen verwenden können, hilft oft.
12982900cookie-checkLeistungsvorteile von Daten in Potenzen von 2?yes
Ich denke, es hängt von der Art des Arrays ab. Nicht-Byte-Typen erfordern möglicherweise eine Speicherausrichtung.
– Vulkanino
1. März 2012 um 11:43 Uhr
In diesem Fall ist jedes Objekt im Chunk 16 Bit oder vielleicht eine andere Potenz von 2 groß (definitiv eine ganze Zahl von Bytes). Ich möchte wissen, ob 150 16-Bit-Objekte langsamer sind als 128 (beachten Sie, dass es immer noch genauso viele Objekte gibt, sie würden nur in mehr Teile aufgeteilt).
– Greg
1. März 2012 um 11:45 Uhr
Stellen Sie sich vor, Sie haben 1000 Personen zu transportieren und Sie haben Busse mit einer Kapazität für 50 Personen. Was ist deiner Meinung nach besser? Menschen in Gruppen von 50 gruppieren oder sie in Gruppen von 72 (oder 38 oder was auch immer) gruppieren und Gruppen aufteilen, bevor die Busse gefüllt werden?
– pmg
1. März 2012 um 11:53 Uhr
Stellen Sie sich vor, die Leute haben verschiedenfarbige Hüte. Wenn Sie sie nach einer anderen Zahl als der Buskapazität gruppieren, hat jeder Bus Menschen mit andersfarbigen Hüten. Die Verwendung von Zweierpotenzen für Array-Dimensionen verbessert die Wahrscheinlichkeit, dass jede Array-Gruppe (von
index
bis kurz davorindex + 1
) belegt einen Teil des Speichers, auf den als Ganzes zugegriffen werden kann.– pmg
1. März 2012 um 12:03 Uhr
Als Wort der Warnung: Die Verwendung von Zweierpotenzen kann zu Super-Alignment-Konflikten führen. Siehe dies und das. Super-Ausrichtung (von Power-of-two-Schritten) kann die Leistung leicht um das Dreifache oder mehr verringern. Was Sie also durch den Handel gewinnen, multipliziert sich mit Schichten, kann leicht (um ein Vielfaches) durch Cache-Fehler und falsche Aliasing-Stalls verloren gehen.
– Mystisch
7. März 2012 um 6:39 Uhr