Warum sind Oktbäume so viel häufiger als Hash-Tabellen?

9

Beim Lesen von Artikeln finde ich häufig Oct-Tree-Implementierungen von Geometriedarstellungen, um die Daten zu sortieren. Wenn ich jedoch über das Problem nachdenke, scheinen Hash-Tabellen insgesamt besser zu sein.

Hash-Tabellen bieten für die meisten Anwendungen bessere Durchschnitts- und schlechtere Szenarien:

Wenn Sie beispielsweise einen Okt-Baum durch Raytracing verfolgen, werden Sie durch Beinaheunfälle durch eine binäre Baumsubstruktur iteriert, die O (nlogn) ist, während die Hash-Tabelle O (n) ist.

Hash-Tabellen sind in der GPU einfacher zu generieren, da sie keine andere logische Position im Speicher als ihre Hash-Position benötigen.

Die meisten Vorteile, die Baumstrukturen gegenüber Hash-Tabellen haben, scheinen auch auf der GPU nicht zu gelten.

In Grafiken mögen wir es nicht, Speicher neu zuzuweisen, daher weisen wir normalerweise zu viel Speicher im VRAM zu, um eine Datenstruktur wiederverwenden zu können. Daher scheinen die Eigenschaften von Binärbäumen (speichereffizient) für GPU-Anwendungen nicht sehr relevant zu sein.

Die Datenkohärenz für das Caching scheint ebenfalls nicht zu gelten. Bei einem GPU-generierten Baum ist es aufgrund der Asynchronität sehr schwierig zu gewährleisten, dass logisch geschlossene Werte auch im zugrunde liegenden Speicher nahe beieinander gespeichert werden. Sie werden also sowieso um Zeiger herumspringen.

Es ist auch viel einfacher, bestimmte GPU-freundliche Heuristiken in einer Hash-Tabelle zu erzwingen als in einem Baum. Begrenzen Sie beispielsweise die Anzahl der Hash-Lookups auf eine feste Anzahl, z. B. 20, und verwenden Sie dieselbe Logik, um zu verhindern, dass Warps unterschiedliche Verzweigungscodes ausführen. Im Wesentlichen können Sie immer die 20 möglichen Kollisionen überprüfen und das Ergebnis einfach mit der Zelle interpolieren, die den Schlüssel enthält. In einem Baum hängt das Durchlaufen der Datenstruktur viel mehr von den Daten selbst und weniger von der Datenstruktur ab.

Warum werden Okt-Bäume so viel häufiger verwendet als Hash-Tabellen?

Makogan
quelle
Weil Octrees einfacher zu schreiben sind als Hashtabellen, nehme ich an?
Patapom
2
Wie ist ein Baum einfacher zu schreiben als eine Hash-Tabelle? Eine Hash-Tabelle ist eine eindimensionale Struktur, und der Okt-Baum ist eine 4-dimensionale Struktur, die auf ein eindimensionales Speicherarray abgebildet ist. Ich habe beide geschrieben und Hash-Tabellen sind so viel einfacher als Okt-Bäume.
Makogan
2
Imo liegt der Hauptvorteil in der Hierarchie, die durch die Verwendung einer Baumstruktur erzeugt wird. Dies führt dazu, dass eine große Anzahl von Knoten bereits beschnitten wird, wenn ein Strahl keines der Felder der oberen Ebene schneidet. Im Gegensatz dazu muss ein Raster den Schnittpunkt mit allen geschnittenen Zellen überprüfen. Diese Antwort erklärt es ziemlich gut. gamedev.stackexchange.com/questions/69776/...
gallickgunner
Mike Acton hat kürzlich eine relevante Präsentation gemacht :) Check out @ mike_actons Tweet: twitter.com/mike_acton/status/1062458276812451840?s=09
Alan Wolfe
@gallickgunner Das ist nur für eine einmalige Kollision effizient, um die Region im Baum zu finden, in der Ihre Daten gespeichert sind. Die meisten Effekte erfordern jedoch die Abtastung mehrerer benachbarter Bereiche (AO, Emission, diffuse Reflexionen ....). Wofür die Hash-Tabelle besser ist. Und Sie können die Hierarchie des Baums mithilfe einer Hash-Mipmap nachahmen. Es gibt Ihnen genau die gleiche Hierarchie und genau die gleiche asymptotische Rechenzeit.
Makogan

Antworten:

5

Meine 2 Cent beim Schreiben der Chipmunk2D-Physik-Engine sind, dass räumliches Hashing großartig ist, wenn Sie viele Objekte haben, die alle gleich groß sind. Ich hatte vor 10 Jahren eine Demo, die mit 20.000 interagierenden Partikeln auf einem Core 2 Duo in Echtzeit lief. Der räumliche Hash hat dafür hervorragend funktioniert, wenn Sie ihn optimiert haben .

Ich habe seitdem den räumlichen Hash durch einen binären AABB-Baum als Standardstruktur ersetzt. Es ist alles andere als perfekt, aber es war im Durchschnitt schneller als der räumliche Hash ohne Abstimmung . Es war auch einfacher, eine zeitliche Komponente hinzuzufügen, damit ich eine Reihe potenzieller Kollisionen schrittweise aktualisieren konnte. Mit all dem war der einzige Test, den ich hatte, der mit dem räumlichen Hash schneller lief, der mit Tausenden von Partikeln und ohne statische Geometrie.

Was Octrees betrifft ... Meh, ich benutze sie nie. Grundlegende Quad / Octrees passen nicht wirklich zu realen Daten sowie zu der Fülle anderer BVHs, die Sie verwenden können. Grund AABB Bäume sind fast so einfach und Weise effektiver.

slembcke
quelle
"Mit dem räumlichen Hash waren es diejenigen mit Tausenden von Partikeln und ohne statische Geometrie." Genial, genau daran arbeite ich, das heißt, meine Intuition darüber war richtig!
Makogan
8

Viele Dinge hier.

  • "Beim Lesen von Zeitungen". Welche Papiere? Wenn es bei dem Thema des Papiers um etwas anderes als die räumliche Aufteilungsstruktur geht, kann es fair sein, alles zu verwenden, wenn man weiß, dass die Grundideen auf andere Strukturen übertragen werden. Oder nicht, schwer zu sagen.

  • "Zum Beispiel für die Raytracing-Funktion eines Okt-Baums führen Beinahe-Fehler dazu, dass Sie eine binäre Baum-Substruktur durchlaufen, die O (nlogn) ist, während die Hash-Tabelle O (n) ist." Big O-Notation bedeutet in diesem Zusammenhang überhaupt nichts. Sie haben es mit einer bestimmten Technologie in einem bestimmten Maßstab zu tun, wenn Sie über Dinge sprechen, die von Implementierungsdetails abhängen. Ein O (nlogn) -Algorithmus ist möglicherweise viel langsamer als ein O (n) -Algorithmus für das "n", was heute realistisch ist. Es kommt immer wieder vor. Und während Sie vielleicht sagen, dass sich dies in 10 Jahren ändern könnte, könnte dies der Fall sein, aber in denselben 10 Jahren könnte Ihre GPU völlig anders aussehen und daher müssen sich die Algorithmen auf dem neuesten Stand der Technik unabhängig davon ändern. Dies ist häufig der Fall, wenn Sie sich GPU-Algorithmen ansehen (und GPUs entwickeln sich noch ziemlich weit).

  • Welcher Octree? Welche Hash-Tabelle? Dort gibt es viele Möglichkeiten. Zum Beispiel "... da sie keine andere logische Position im Speicher als ihre Hash-Position benötigen". Das stimmt nur, wenn Sie keine Hash-Kollisionen haben, ja? Wenn Sie Kollisionen haben, müssen Sie unabhängig von der von Ihnen verwendeten Strategie (Prüfung oder verknüpfte Listen) zwischen Threads synchronisieren, damit der Build auf einer GPU nicht so einfach implementiert werden kann. Umgekehrt könnten Sie für Oktrees, wenn Sie wie von Ihnen vorgeschlagen "insgesamt zuordnen" möchten, einen vollständigen Baum zuweisen, und die Indizierung wäre dann ebenfalls nur von der Position abhängig. In der Tat, wenn Sie etwas rechnen, können Sie sehen, dass in solchen Fällen Oktrees nur eine Möglichkeit sind, ein Raster zu verwirren (z. B. vergleichen Sie das Van-Ende-Boas-Layout mit einem Raster in Morton-Reihenfolge ... schöne Übung).

Es gibt viele andere Dinge, die ich sagen könnte, aber lassen Sie mich hier zur Sache kommen.

  • Für das Raytracing sind weder Octrees noch Hash-Tabellen so beliebt. BVHs von AABBs sind der richtige Weg.

  • Der Hauptvorteil von Octrees gegenüber dem Hash-Raster besteht darin, dass sich Ihre Zellenauflösung an die Geometrie anpasst. Raster werden nicht, Sie müssen eine Zellengröße auswählen, die in bestimmten Teilen der Szene zu klein und in bestimmten anderen zu groß sein kann.

  • Es gibt eine Vielzahl von Varianten und eine Vielzahl von Implementierungsdetails. Naive Octrees sollten in der Praxis wahrscheinlich nie verwendet werden, da sie zu tief / nicht breit genug sind. Wenn Sie ein Octree "größer" machen, indem Sie beispielsweise ein 4x4x4-Gitter mit 4x4x4-Gittern in jeder nicht leeren Zelle verschachteln, erstellen Sie ein sogenanntes hierarchisches Gitter. Gitter und Oktrees existieren also in einem Spektrum, in dem Oktrees am "tiefsten" sind, Gitter am "flachsten" sind (nur eine Ebene, ein einzelnes Gitter global in der Szene) und hierarchische Gitter zwischen den beiden handeln können

  • Das könnte helfen! http://www.realtimerendering.com/Real-Time_Rendering_4th-Real-Time_Ray_Tracing.pdf ;)

Angelo Pesce
quelle
Sie können Hash-Kollisionen problemlos durchführen, ohne dass eine größere Synchronisierung erforderlich ist, indem Sie die Anzahl der möglichen Kollisionen auf eine bekannte Anzahl (z. B. 20) beschränken und atomare Operationen für ein Flag verwenden. Bei kompakten Okt-Bäumen, wie sie durch Voxel Global Illumination und Oct-Tree-basierte Algorithmen generiert werden, benötigen Sie zwei separate Shader, die jeden anderen in einer Schleife aufrufen, um eine Speicherzuweisung zu erreichen. Und "normale" Okt-Bäume (diejenigen, bei denen Sie den Index anhand einer festen Funktion kennen) erzeugen viel unbenutzten Speicher. Zu diesem Zeitpunkt ist ein 3D-Volumen wahrscheinlich besser.
Makogan
Ich denke auch, dass Sie die Komplexität Ihrer Erklärung der asymptotischen Komplexität ausgetauscht haben, die bei modernen Algorithmen aufgrund der Veränderbarkeit der Hardware
kein Problem darstellt