Räumliche Unterteilung mit boost-Unterstützung

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Niki
Establishment
Beiträge: 309
Registriert: 01.01.2013, 21:52

Räumliche Unterteilung mit boost-Unterstützung

Beitrag von Niki »

Heute mal ein grafisch angehauchtes Programmierthema :) Wie sich einige hier denken können ist meine bisherige Erfahrung mit boost eher lütt. Das möchte ich ändern, allerdings ohne dabei in das "hauptsache boost"-Extrem zu verfallen. Auf Dauer ist es mein Ziel zu lernen wo und wann boost einen wesentlichen Vorteil bringt.
Momentan, zum Beispiel, arbeite ich an einer räumlichen Unterteilung meiner 3D Spielwelt, und ich frage mich ob es boost-Features gibt die mir hier einen wirklichen Vorteil verschaffen können. Im folgenden eine kurze Erklärung wie meine räumliche Unterteilung aufgebaut ist, und danach eine Übersicht wo ich mir Verbesserungen wünschen würde (sofern sinnvoll).

Klasse: Spatial
Ein Spatial kann alles mögliche sein, wie zum Beispiel ein Monster, ein kleiner Szenengraph, etc.

Klasse: SpatialQuadTree
Bei der Klasse SpatialQuadTree handelt es sich um einen Loose Quad-Tree. Die einzelnen Knoten des Quad-Trees sind vom Typ SpatialPartition. Sämtliche Knoten werden in einem linearen Array gespeichert (momentan std::vector). Das bedeutet auch, dass alle Knoten für die gesamte Baumtiefe von Anfang an reserviert sind. Die einzelnen Knoten werden nicht separat per new-Operator reserviert, sondern die Objektinhalte stehen direkt im Array (also keine Zeiger, da ich Cache Misses reduzieren will)

Klasse: SpatialPartition
Eine SpatialPartition stellt, wie gesagt, einen Knoten des Quad-Trees dar. SpatialPartitions enthalten eine doppelt-verkettete Liste von Objekten des Typs Spatial. Zu diesem Zweck enthält eine SpatialPartition je einen Zieger auf das erste und das letzte Spatial Objekt, während die Spatial-Klasse selbst Zeiger auf Vorgänger- und Nachfolger-Spatials enthält. Diese Art Liste reduziert wiederum Cache Misses, da es keine separat reservierten Knoten für die Vorgänger- und Nachfolger-Zeiger gibt. Auch ist das Einfügen und Entfernen von Spatials auf diese Weise sehr schnell.

Ok, effizient ist das, hat aber auch den Nachteil das Spatials nun nicht mittels shared_ptr gespeichert werden. Sofern sich das als sinnvoll erweist würde ich das gerne ändern, bin mir aber momentan nicht sicher wie ich die doppelt-verkettete Liste damit erstelle ohne großartig Nachteile zu erzeugen. Momentan ist zum Beispiel die sizeof-Größe der SpatialPartition-Klasse so klein wie möglich gehalten um Cache Misses zu reduzieren. Wenn ich nun shared_ptr's für die Start- und Endknoten der verketteten Liste verwende, dann erhöhen sich Speicherverbrauch und somit Cache Misses. Hat da jemand eine geniale Idee?

Das zweite Thema hat mit Callbacks zu tun. Ich möchte den Quad-Tree mit AABBs durchlaufen und alle Spatials enumerieren die diesen AABB schneiden. Je nach Aufgabe (Rendern, Kollisionsabfrage, etc.) sollen Callbacks mit verschiedener Funktionalität aufgerufen werden. Mein erster Ansatz wäre hier eine Basisklasse a là SpatialEnumerator zu bauen, und darin eine virtuelle Methode Enumerate() zu haben, die von einer abgeleiteten Klasse überladen werden kann. Ich frage mich ob es da vielleicht noch schönere Ansätze via boost gibt, die auch einen wirklichen Vorteil bringen?

EDIT: Anregungen und Kommentare die nichts mit boost zu tun haben sind selbstverständlich auch erwünscht :)
Benutzeravatar
Jonathan
Establishment
Beiträge: 2398
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Räumliche Unterteilung mit boost-Unterstützung

Beitrag von Jonathan »

Mal so ganz nebenbei: Wieso shared_ptr? Die sind um einiges teurere, als unique_ptr. Früher brauchte man die, um Smartpointern in Containern speichern zu können, mit unique_ptr ist das aber Geschichte.
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Niki
Establishment
Beiträge: 309
Registriert: 01.01.2013, 21:52

Re: Räumliche Unterteilung mit boost-Unterstützung

Beitrag von Niki »

Das ist genau der Grund warum ich diesen Thread geschrieben habe. Ich bin ein echter boost-Noob und versuche das bei der Entwickung meines "Szenengraphen" zu ändern. Wenn man etwas nicht oft benutzt dann vergisst man es schnell. So habe ich unique_ptr zwar schon gesehen, aber wieder vergessen weil ich's noch nicht benutzt habe :)

EDIT: Cool! Das ist sogar von der STL. Muss recht neu sein. Werde mal schauen ob mir das weiterhilft. Danke, Jonathan.
Niki
Establishment
Beiträge: 309
Registriert: 01.01.2013, 21:52

Re: Räumliche Unterteilung mit boost-Unterstützung

Beitrag von Niki »

Okay, ich habe mir den unique_ptr nun mal reingezogen. Vorausgesetzt das ich alles korrekt verstanden habe, verstehe ich nicht so ganz wie mir das in meinem Fall weiterhelfen kann. Das liegt aber auch daran, dass ich hier nicht meinen gesamten Engine-Aufbau erläutert habe. Der SpatialQuadTree ist nur ein kleiner Teil des Szenengraphen, und die Spatials sind Basisklassen für alle möglichen Knotentypen des Szenengraphen. Über Referenzknoten muss es mir möglich sein, dasselbe Spatial Objekt mehrfach im Szenengraph zu benutzen, wodurch mehrere Zeiger auf dasselbe Objekt entstehen.

Bitte korrigiert mich falls ich da was verpasst habe :)
Benutzeravatar
Jonathan
Establishment
Beiträge: 2398
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Räumliche Unterteilung mit boost-Unterstützung

Beitrag von Jonathan »

Ein unique_ptr ist dafür da, dass ein Objekt (auf das der Zeiger zeigt) genau einen Besitzer hat - wird dieser zerstört, wird auch das Objekt zerstört. Im Gegensatz zum auto_ptr von damals, kann der Besitzer aber gewechselt werden, dann wird das Objekt später einmal vom neuen Besitzer zerstört, es gibt also zu jedem Zeitpunkt genau einen definierten Benutzer. Weil in einem Container Objekte hin und her geschoben werden, ist der unique_ptr dafür gut geeignet.

Die Frage die du dir Stellen musst, ist, ob ein Spatial nur einen Besitzer hat, oder mehrere. In meinen Programmen ist quasi immer ersteres der Fall, wenn man Objekte Rendern will oder so, hat man die eigentlich immer irgendwo zentral gespeichert. Jeder andere Objekt hat dann nur einen ganz normalen Pointer auf das Objekt, der Verwalter hat einen unique_ptr. Netterweise erkennt man so schon an der Pointer-Deklaration, ob das Objekt hier gespeichert wird oder nur von hier darauf zugegriffen wird. Oh, und dadurch, dass alles, was mit new angelegt wird, konsequent in einen unique_ptr kommt, sind Memory-Leaks auch quasi unmöglich (es sei denn, man legt es wirklich darauf an).
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Niki
Establishment
Beiträge: 309
Registriert: 01.01.2013, 21:52

Re: Räumliche Unterteilung mit boost-Unterstützung

Beitrag von Niki »

Danke für die Zusammenfassung. Du erklärst es genau so wie ich es verstanden haben.
Jonathan hat geschrieben:Die Frage die du dir Stellen musst, ist, ob ein Spatial nur einen Besitzer hat, oder mehrere.
Es ist bei mir in der Tat so, dass ein Spatial mehrere Besitzer haben kann. Die Idee mit dem Verwaltungsobjekt ist mir, im Zusammenhang mit unique_ptr, auch schon gekommen. Die Entscheidung ein Verwaltungsobjekt einzuführen habe ich zu diesem Zeitpunkt zwar noch nicht getroffen, aber ich habe ein paar Threads in meinem Hirn für diesen Zweck reserviert. Es ist nicht so, dass ich keinen existierenden Code habe, und deshalb muss ich Aufwand und Risiko abschätzen. Bei einer zentralen Verwaltung würde ich dann wahrscheinlich eine Art Factory bauen. Aber da bin ich wie gesagt noch am Überlegen.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Räumliche Unterteilung mit boost-Unterstützung

Beitrag von dot »

Niki hat geschrieben:Es ist bei mir in der Tat so, dass ein Spatial mehrere Besitzer haben kann.
Wieso?
Niki
Establishment
Beiträge: 309
Registriert: 01.01.2013, 21:52

Re: Räumliche Unterteilung mit boost-Unterstützung

Beitrag von Niki »

dot hat geschrieben:
Niki hat geschrieben:Es ist bei mir in der Tat so, dass ein Spatial mehrere Besitzer haben kann.
Wieso?
Ganz ehrlich? Alter Code, altes Design :) Ich kann in dem Code noch Geometrie-Knoten haben die von mehreren anderen Knoten benutzt werden. Dummerweise sind die Teil des Szenengraphen. Und ja, dot, ich weiß schon was du jetzt denkst, und ich denke dasselbe. Vielleicht sollte ich das ganze Ding mal generalüberholen (neu bauen). Das würde vieles vereinfachen, und ich würde eine ganze Menge Ballast von vor 10 oder so Jahren loswerden.
Niki
Establishment
Beiträge: 309
Registriert: 01.01.2013, 21:52

Re: Räumliche Unterteilung mit boost-Unterstützung

Beitrag von Niki »

Ok, ich hab's jetzt überschlafen und mich entschieden. Das alte Ding wird neu gebaut. Das wirft mich zwar mächtig zurück, aber das kann ich mir leisten, da es momentan noch ein Hobbyprojekt ohne Deadline ist. Auch die Menge des neugeschriebenen Codes, der auf dem alten basiert, ist noch gering genug um mit eventuellen Inkompatibilitäten klarzukommen. Also, zentrale Knotenverwaltung, Knoten mit nur einem Besitzer, und eine separate Geometrieverwaltung, sind angesagt. Das hätte ich damals schon tun sollen, aber das ist heute leicht gesagt, denn früher hatte ich den Zeitdruck den ich heute nicht habe. Auch die Unterstützung neuerer Rendering-Techniken wird damit besser. Bisher waren gewisse D3D11 Features schon eher krampfig zu unterstützen, und das nervt ganz schön. Die meisten Experimente mit D3D11 geschahen deshalb auch in separaten "Projekten". Es ist Zeit das zu ändern.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Räumliche Unterteilung mit boost-Unterstützung

Beitrag von dot »

Niki
Establishment
Beiträge: 309
Registriert: 01.01.2013, 21:52

Re: Räumliche Unterteilung mit boost-Unterstützung

Beitrag von Niki »

Danke dot, ich werde mir das nach der Arbeit mal genau durchlesen. Ich kann mir schon denken das es darum geht, dass klassische Szenengraphen in Spielen heutzutage keine so pralle Idee sind. Aber das will ich ja auch gar nicht. Sicherlich werde ich irgendeine Form der Objektorganisation haben, und das evtl. auch Szenengraph nennen, aber mit dem klassischen Szenengraph wird es wenig zu tun haben.
Niki
Establishment
Beiträge: 309
Registriert: 01.01.2013, 21:52

Re: Räumliche Unterteilung mit boost-Unterstützung

Beitrag von Niki »

Also ich muss wohl zu blöd sein. Hier gibt es so viele Leute im Forum die STL/boost bis zum Abwinken benutzen, und ich sehe niemanden der darüber nöselt. Ich sehe immer nur positives. Aber jedesmal wenn's an bestimmte performance-kritische Datenstrukturen geht finde ich keine Lösung mit STL/boost, die auch nur im Entferntesten an die Performance von relativ kurzem, manuellem Code rankommt. Ich gebe mir ja wirklich Mühe, aber irgendwas muss ich falsch machen, denn sonst würde es hier mehr Leute geben die sagen: "Mach besser selbst!".

Ich würde gerne mal ein praktisches Beispiel mit euch durchkauen, mit dem Ziel eine STL/boost Lösung zu finden, die wenigstens annähernd an die Performance meines manuellen Codes rankommt.

Die Aufgabe: Baue eine Factory über die irgendwelche Objekte reserviert werden. Die Factory ist hierbei auch gleichzeitig Besitzer der reservierten Objekte, und damit auch für deren Löschen verantwortlich. Die Factory hat also irgendeine Form von Objektkollektion (also mehr ein "Objektmanager" als eine reine Factory). Die Anzahl der verwaltbaren Objekte sollte sehr hoch sein. Gleichzeitig muss ein Einfügen und Entfernen von Objekten sehr schnell sein.

Hier mal Pseudocode für eine manuelle Variante. Ich weiß, dass er keine Initialisierungen, keine Reservierungen, kein Exception-Handling enthält. Alles was er zeigt ist wie Okjekte vom Typ SgNode in eine Objektkollektion eingefügt werden können, und wie diese auch gelöscht werden können. Und ja, der Code hat die Unschönheit mit der friend-Klasse.

Ich bin schon mal gespannt was ich jetzt noch alles dazu lerne :)

Code: Alles auswählen

class SgNode
{
    friend class SgNodeFactory;

    private:
        SgNode *        m_pPrevFactoryNode;
        SgNode *        m_pNextFactoryNode;
};

class SgNodeFactory
{
    private:
        void InsertNode(SgNode * pNode);
        void RemoveNode(SgNode * pNode);

    private:
        SgNode *        m_pHeadNode;
        SgNode *        m_pTailNode;
};

void SgNodeFactory::InsertNode(SgNode * pNode)
{
    pNode->m_pNextFactoryNode = NULL;
    pNode->m_pPrevFactoryNode = m_pTailNode;

    if (pNode->m_pPrevFactoryNode != NULL)
    {
        pNode->m_pPrevFactoryNode->m_pNextFactoryNode = pNode;
    }
    else
    {
        m_pHeadNode = pNode;
    }

    m_pTailNode = pNode;
}

void SgNodeFactory::RemoveNode(SgNode * pNode)
{
    if (pNode->m_pPrevFactoryNode != NULL)
    {
        pNode->m_pPrevFactoryNode->m_pNextFactoryNode = pNode->m_pNextFactoryNode;
    }
    else
    {
        m_pHeadNode = pNode->m_pNextFactoryNode;
    }

    if (pNode->m_pNextFactoryNode != NULL)
    {
        pNode->m_pNextFactoryNode->m_pPrevFactoryNode = pNode->m_pPrevFactoryNode;
    }
    else
    {
        m_pTailNode = pNode->m_pPrevFactoryNode;
    }
}
Bitte beachten! Das ist abgespeckter Pseudocode. Kann Fehler enthalten. Ist nicht als Referenz gedacht.

EDIT: Ich sollte vielleicht noch anmerken, dass SgNode nicht einfach einen separaten Listenknoten darstellt. SgNode ist gleichzeitig die Basisklasse für die Objekte die über die Factory erzeugt und verwaltet werden.
Benutzeravatar
Schrompf
Moderator
Beiträge: 4886
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas
Wohnort: Dresden
Kontaktdaten:

Re: Räumliche Unterteilung mit boost-Unterstützung

Beitrag von Schrompf »

Hm. Ich stimme Dir zwar zu, dass speziell bei hochperformantem Code, den man mit Kontextwissen optimieren kann, Boost oder die STL nicht ideal sind. Aber davon sehe ich in Deinem Beispielcode dann gar nichts mehr. Korrigiere mich, wenn ich Dich missverstehe, aber Deine Anforderungen lauten:

- eine Factory, die Objekte nach irgendwelchen ungenannten Kriterien erzeugen kann
- und gleichzeitig ein Container für alle erzeugten Objekte

Ich weiß nun schonmal nicht, was es bringen soll, eine Factory und einen Container zu kombinieren. Was für Vorteile ergeben sich daraus? Ich habe mir für eine Factory ein kleines Template-Konstrukt gebastelt, dass anhand eines Parameters Objekte verschiedener Typen erzeugen kann. Die werden dann einfach zurückgegeben und fertig. Der Container für die Instanzen ist meines Erachtens eine komplett unabhängige Aufgabe.

Der von Dir skizzierte Code hat damit aber wiederrum nix zu tun. Das ist, wenn ich das richtig verstehe, eine Standard-Doppelt verlinkte Liste. std::list ist exakt das, und sollte gegenüber Deinem Code auch exakt genauso performen. Jetzt mal abgesehen von Visual Studio im Debug Build, wo die Iterator Validation ganz besonders die Listen praktisch unbrauchbar macht. Aber Listen sind auch in Sachen Cache-Kohärenz eine miese Idee, wenn man öfter drüberiterieren will als Knoten hinzufügen oder entfernen. Und nach meiner Erfahrung sind Objektsammlungen in Spielen doch eher statisch - Änderungen daran passieren im Durchschnitt alle 100 Frames oder so.

Ich vermute jetzt mal über den Beispielcode hinaus: Du suchst boost::intrusive_list. Da ist das Objekt auch sein eigener Listenknoten, weswegen man das zweite new für den Listenknoten spart, was sonst in einer Standard-Listenimplementierung anfällt. Bei Listen mit vielen zehntausenden Elementen bringt das tatsächlich einen Rechenzeit-Vorteil, aber bei solchen Containergrößen ist die Liste allgemein eine dumme Idee. Wegen oben genannter Cache-Kohärenz. Man könnte das verbessern, indem man einen Custom Allocator benutzt, aber das war mir bisher zuviel Arbeit. Es gibt ja wirklich eine Menge besserer Container als Listen. Eigentlich sind *alle* Container besser, außer unter ganz bestimmten und meiner Meinung nach sehr seltenen Umständen.

Meine Lösungsvorschläge für das vermutete Problem wären also:

a) boost::intrusive_list
b) falls Reihenfolge der Elemente egal ist: std::vector<BasisKlasse*>. Beim Löschen einfach std::swap() des Elements mit dem letzten Element und dann pop_back(), Einfügen immer hintendran.
c) meine Lösung, ebenso aus uraltem Code: eine eigene Array-Klasse mit dem Element-Array und einem zweiten Array aus bools, welcher Array Slot besetzt ist und welcher nicht. Das Entfernen eines Elements ist dann immer O(1), das Hinzufügen kann man mit simplen Tricks auf O(1) kriegen, aber das Drüberiterieren braucht ein if() pro Element. Läuft aber immernoch deutlich besser als std::list wegen der oben genannten Cache-Kohärenz.

Da das aber nunmal alles nur Lösungen für ein Problem sind, das ich nur vermute, frag ich mal anders: Wie sieht der äquivalente STL-Code aus, und wieviel langsamer ist der im Vergleich zu Deiner Lösung?
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Niki
Establishment
Beiträge: 309
Registriert: 01.01.2013, 21:52

Re: Räumliche Unterteilung mit boost-Unterstützung

Beitrag von Niki »

Mein Urlaub ist vorbei, wodurch Antworten länger dauern. Nur kurz für Schrompf vorab ein Dankeschön und ein kurze Vorabantwort (mehr später, falls nötig):

(1) Ja, ich vermische da Factory und Objektsammlung. Das muss man nicht tun, und ich selbst werde das wahrscheinlich auch getrennt handhaben.
(2) boost::intrusive_list.... Na, wer sagt's denn. So lernt man was dazu! Deiner Beschreibung nach ist das nämlich 100% das was ich haben will. Mir ist es wichtig das die Objekte gleichzeitig die Listenknoten sind. Werde ich mir heute Abend genau anschauen.

Ok, ich muss zurück zu meinen Mobiltelefonen. Programmieren für's BlackBerry Q10 ist heute auf dem Plan.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Räumliche Unterteilung mit boost-Unterstützung

Beitrag von dot »

Ich hab nicht den Eindruck, dass so viele hier boost verwenden, ich selbst z.B. verwend boost praktisch nie. Davon abgesehen: Wenn es um rohe Performance geht, dann bist du mit verlinkten Listen rein prinzipiell schonmal nicht unbedingt am besten Weg... ;)
Benutzeravatar
Schrompf
Moderator
Beiträge: 4886
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas
Wohnort: Dresden
Kontaktdaten:

Re: Räumliche Unterteilung mit boost-Unterstützung

Beitrag von Schrompf »

Ich verwende und schätze von Boost die folgenden Dinge:

- format
- lexical_cast
- signals2
- bind
- thread
- locale
- scoped_ptr
- any

Wobei Teile davon mit dem neuen C++ ja nun schon veraltet bzw. überholt sind. Boost::scoped_ptr hat mit std::unique_ptr und Move Semantics ja nun seine Existenzberechtigung verloren. boost::thread ist ebenso jetzt Teil des Standards geworden. Seit Ewigkeiten will ich außerdem mal in boost::filesystem reinschnuppern - das könnte die Lösung für einige hässliche Probleme sein, die ich hatte. Spirit - der template-basierte Parser-Generator, sieht auch sehr mächtig aus. Boost::any fliegt dagegen bald wieder raus, den boost::property_tree habe ich bereits rausgeworfen. Beide sind ein bisschen über-designed und nicht angenehm zu benutzen.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Niki
Establishment
Beiträge: 309
Registriert: 01.01.2013, 21:52

Re: Räumliche Unterteilung mit boost-Unterstützung

Beitrag von Niki »

Die Zeit nehme ich mir jetzt mal. Bitte stellt Fragen falls es immer noch unklar ist, denn ich schreibe unter Zeitdruck.

In der verketteten Liste sind irgendwelche Objekte direkt verlinkt, d.h. die Objekte selbst sind auch gleichzeitig Linkknoten. Diese Objekte können von allen Möglichen Typen sein, sofern die zugehörige Klasse denn von einer Art Linkknotenklasse abgeleitet wurde.
Mein Ziel ist es nun alle reservierten Objekte in einer einzigen Objektsammlung zu verwalten, wobei jedes einzelne Objekt per new reserviert wird. Diese Objektsammlung ist auch dafür zuständig Objekte zu entfernen und den Speicher freizugeben. Andere Klassen benutzen lediglich die Objektzeiger (welches ja gleichzeitig die Linkknoten sind).
Cache Misses beim Zugriff auf Objektinhalt habe ich sowieso, da alle Objekte einzeln per new reserviert werden. Was ich mir aber spare sind die zusätzlichen Cache Misses von std::list, std::map, etc, da diese meine Objektpointer nochmals in einer separate reservierten Knotenstruktur speichern. Desweiteren habe ich keinerlei Speicherverschieberei.

Zu dem habe ich nicht vor die Objektsammlung von Anfang bis Ende zu durchlaufen, oder irgendwas darin zu suchen oder zu sortieren. Ich benutze sie nur um Objekte einzufügen und zu entfernen. Um Objekte einzufügen oder zu entfernen berühre ich maximal 3 Knoten: das zu entfernende Objekt, das Vorgängerobjekt und das Nachfolgerobjekt. Für's Einfügen ist es dasselbe.

boost::intrusive_list scheint mir genau dieses zu ermöglichen. Heute Abend werde ich das genau wissen.

@Schrompf: Ich kann dir keinen äquivalenten STL Code geben, da mir bisher nicht klar war, wie ich äquivalenten Code erreichen kann. Das geht erst seit du von boost::intrusive_list berichtet hast :) Und selbst damit ist es nicht STL, sondern boost.
Niki
Establishment
Beiträge: 309
Registriert: 01.01.2013, 21:52

Re: Räumliche Unterteilung mit boost-Unterstützung

Beitrag von Niki »

Falls ihr übrigens denken solltet das ich dafür kein boost nehmen sollte, dann sagt es bitte jetzt. Ihr wisst das Zeug ist neu für mich und ich muss mich da ein wenig auf eure Erfahrungen verlassen.
Benutzeravatar
Schrompf
Moderator
Beiträge: 4886
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas
Wohnort: Dresden
Kontaktdaten:

Re: Räumliche Unterteilung mit boost-Unterstützung

Beitrag von Schrompf »

Ob STL oder Booost, ist doch egal :-) Für mich wäre der äquivalente STL-Code gewesen:

Code: Alles auswählen

std::liste<BasisKlasse*> sammlung;
sammlung.push_back( factory.CreateInstance( "AbleitKlasse"));
sammlung.erase( sammlung.begin());
Und dann mal nachmessen. Immerhin ist ein Container dieser Art unendlich viel schneller geschrieben als die eigene Listenklasse. Und dann misst man nach und stellt fest, dass man pro Frame im Durchschnitt nur 50us eingebüßt hat und das initiale Laden von 10k Objekten mit der Standard-STL-Liste nur 5ms länger dauert. Und das predige ich ja die ganze Zeit: nachmessen! Nicht vermuten, nicht raten, nicht vorab loseilen und Dinge optimieren. MESSEN!

Und wenn man dann wirklich feststellt, dass der Profiler ab 100k Objekten und 100 Einfügungen und Löschungen pro Frame einen signifikanten Teil der Rechenzeit in der std::list verbringt, DANN kann man sich ne Platte machen, was man dagegen tut. Und das schöne ist, dass jede Lösung, die man dann anstatt der anfänglichen schlichten Liste erfindet, schnittstellenkompatibel ist. Damit haben es auch alle anderen Programmierer, die mal an dem Projekt mitarbeiten sollen, viel einfacher, den Code zu verstehen. Die Namen und die Funktionsweisen sind den neuen Leuten dann schon vertraut, obwohl es alles Dein Code ist. Einfach weil Dein Code sich genauso verhalten muss wie der bisherige std::list-Code, damit der selbstgeschriebene Ersatz seinen Dienst tut.

Ob und wieweit diese Vertrautheit dann auch für Boost gilt, ist streitbar. Ich empfinde Boost als eine Sammlung von Tools und Tricks, um mir Arbeit zu ersparen. Andere Leute mögen Boost nicht... von mir aus. Boost ist halt eben nicht DER STANDARD, sondern nur eine externe Bibliothek wie jede andere auch. Nur halt von ziemlichen Profis geschrieben und besser getestet und gepflegt als die meisten.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Räumliche Unterteilung mit boost-Unterstützung

Beitrag von dot »

OT: boost.filesystem ist ganz nice, kommt wohl mit C++14 im Standard und is afaik in Visual C++ schon enthalten.
Niki
Establishment
Beiträge: 309
Registriert: 01.01.2013, 21:52

Re: Räumliche Unterteilung mit boost-Unterstützung

Beitrag von Niki »

Messen kann ich jetzt noch nicht so einfach, da es noch nichts realistisches zu messen gibt. Klar kann man schon irgendwelche Performance-Tests machen, aber das ist momentan auch eher theoretisch.

Warum also die ganze Aktion?

1. Ich bin neugierig und lernen ist wichtig.

2. Wie du schon sagtest ist Code mit einem STL Container wesentlich schneller geschrieben. Da mein Projekt größer ist möchte ich von dieser Tatsache Gebrauch machen.

3. Nach den Diskussionen in diesem Thread kann ich mir sicher sein, dass ich z.B. erstmal mit einem std::vector anfangen kann. Und wenn das zu langsam sein sollte, dann weiß ich wenigstens, dass ich das recht einfach ändern kann (z.B. mit boost::intrusive_list. Sieh's als eine Art der Absicherung für die Zukunft, denn es wird sehr viel Code geben, der Objekte aus der Objektsammlung benutzt. Letztendlich dient die nur einem Ziel... korrekte Speicherfreigabe von Objekten die an vielen Stellen und in möglicherweise komplexen Situationen benutzt werden.

EDIT: Da ich jetzt aber schon über boost::intrusive_list gehört habe, werde ich sie auch direkt einsetzen.
Benutzeravatar
Schrompf
Moderator
Beiträge: 4886
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas
Wohnort: Dresden
Kontaktdaten:

Re: Räumliche Unterteilung mit boost-Unterstützung

Beitrag von Schrompf »

Ja, tu das! Lernen ist wichtig - ich lerne jeden Tag noch was Neues, und das finde ich spannend an diesem Beruf. Ich will hier auch keine Lanze für irgendein konkretes Stück Code brechen - egal ob Boost oder nicht. Es gibt immer sinnvolle Libs da draußen, die einem ein Stück Arbeit abnehmen können, und es gibt genauso auch Grütze, die im Kontext der aktuellen Aufgabe mehr hindert als nützt.

Ich habe halt den Eindruck gewonnen, dass speziell im C++-Bereich viel zu viel selbst geschrieben wird, und als Gründe dafür werden meistens meiner Meinung nach "falsche" Gründe angegeben. Die Gründe lauten "xyz ist zu langsam für meine Zwecke" oder "blablubb macht die Kompilierung zu aufwändig", aber wenn ich nachbohre, stelle ich meist fest, dass die Leute das nie selbst ausprobiert und festgestellt haben, sondern es eher auf eine Art Gesamteindruck zurückgeht, den die Leute von hundert kleinen Quellen im Internet gewonnen haben. Und damit sind die Gründe inherent veraltet und wie bei dem Kinderspiel "stille Post" bis zur Unkenntlichkeit verfälscht und vereinfacht, Denn wenn man mal nachmisst, stellt man speziell bei der STL oder bei Boost fest, dass die eigene Lösung der "offiziellen" bei weitem nicht das Wasser reichen kann. Und ich ackere öffentlich, damit die Leute das auch mal feststellen.

Dass ich jetzt ausgerechnet Dein Problem dazu zum Anlass genommen habe, ist dann mehr Zufall als alles andere. Sorry :-)
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Niki
Establishment
Beiträge: 309
Registriert: 01.01.2013, 21:52

Re: Räumliche Unterteilung mit boost-Unterstützung

Beitrag von Niki »

Keine Sorge, wenn du mein Problem zum Anlass genommen hast. Unrecht hast du ja auch nicht, da mein eigener Engine Code von vor 10 Jahren ist. Ist glaube sogar mehr, aber ich fühle mich so alt wenn ich das schreibe :D Und die andere üble Erfahrung mit der Kompilierzeit ist auch schon 7 Jahre her.

Übrigens glaube ich nicht (und habe ich auch nie geglaubt), dass die STL/boost Algorithmen langsam sind. Die sind schon schnell, und bei einigen Dingen habe ich da früher sogar Ansätze aus der STL geborgt. Mein Problem ist nun, dass die Zeit nicht stehen geblieben ist und ich viel neues nachholen muss. Manchmal resultiert das bestimmt in Fragen wo sich manche denken müssen "Wieso? Warum? Ja, spinnt der denn!". Das war jetzt natürlich nur Spaß, aber du verstehst schon wovon ich rede.
Antworten