Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

LukasBanana

Alter Hase

  • »LukasBanana« ist der Autor dieses Themas

Beiträge: 1 097

Beruf: Shader Tools Programmer

  • Private Nachricht senden

1

03.07.2014, 23:38

C++ Library Extension

Hallo zusammen,
heute stelle ich mal ein kleines (nicht Spiele-) Projekt vor. Aber vielleicht kann ja trotzdem jemand was damit anfangen.

Ich habe mich heute mal intensiver mit den Variadic Templates in C++11 beschäftigt und eine eigene "multi_array" Klasse geschrieben.
Als Erweiterung zu std::array. Boost bietet zwar bereits eine gleichnamige Klasse, aber da finde ich die Syntax nicht so schön:

Auszug aus der Boost Docu:

C-/C++-Quelltext

1
boost::multi_array<double, 3> A(boost::extents[3][4][2]);


Mit meiner Klasse sieht das ganze so aus:

C-/C++-Quelltext

1
multi_array<double, 3, 4, 2> A;


Ich weiß jetzt nicht genau wie die Klasse in Boost umgesetzt ist, aber wenn sie es richtig gut gemacht haben (und davon gehe ich einfach mal aus),
dann hat das boost::multi_array gegenüber den ANSI-C multi-arrays keinen Overhead (in Speicherbedarf und Zugriffszeiten).

Mit dem Projekt habe ich heute erst angefangen, aber was den Speicherbedarf angeht (inkl. Cache-Lokalität) zieht es bereits mit den ANSI-C arrays gleich.
Das funktioniert mittels Template-Meta-Programming. Für viele ein Graus aber die entsprechenden Templates sind vom Nutzer weg-gekapels (teilweise in dem "details" namespace genau wie in Boost).

Darüber hinaus ist die Klasse standardkonform, d.h. sie kann mit "std::sort", for-each Schleifen etc. benutzt werden.
Zur Zeit funktionieren nur die Reverse-Iteratoren noch nicht.

Wie gesagt, das Projekt ist noch jung, aber falls jemand Interesse hat, hier ist das Git Repository (Öffentlich zugänglich unter der 3-Klausel BSD Lizenz).
Und hier der Link zur multi_array.hpp Datei.

Compiler Infos:
Kompiliert werden kann das ganze ab den folgenden Compiler Versionen:
- MSVC12
- GCC 4.7 (-std=c++11)
- clang 3.4 (-std=c++11).

Gruß,
Lukas

UPDATE:
Das Repository ist jetzt auf github

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »LukasBanana« (21.09.2014, 16:29)


eXpl0it3r

Treue Seele

Beiträge: 386

Wohnort: Schweiz

Beruf: Professional Software Engineer

  • Private Nachricht senden

2

04.07.2014, 08:54

(Öffentlich zugänglich unter der LGPLv3).
Da es sich im eigentlichen um eine einzige Datei handelt (header-only) wäre eine Datei basierende Lizenz wohl etwas mehr angebracht, z.B. MPL 2.

boost::multi_array gegenüber den ANSI-C multi-arrays keinen Overhead (in Speicherbedarf und Zugriffszeiten).
In wiefern gibt es da einen oder eben keinen Overhead?

Da das Ganze ein Container ist, wäre es wohl noch interessant ein paar Angaben (Speicherzugriffe, Speicherbedarf, etc.) in der O-Notation zu haben.
Blog: https://dev.my-gate.net/
—————————————————————————
SFML: https://www.sfml-dev.org/
Thor: http://www.bromeon.ch/libraries/thor/
SFGUI: https://github.com/TankOs/SFGUI/

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

3

04.07.2014, 09:17

Da das Ganze ein Container ist, wäre es wohl noch interessant ein paar Angaben (Speicherzugriffe, Speicherbedarf, etc.) in der O-Notation zu haben.

Der Speicherbedarf ist offensichtlich genau wie bei normalen Arrays.
Um die Adresse eines Elements im N-dimensionalen Array zu bestimmen, braucht man N-1 Multiplikationen und N-1 Additionen.
Die kann man jedoch gegenüber dem eigentlichen Speicherzugriff vernachlässigen.

Sieht übrigens sehr cool aus, diese "Library"! :)
Danke fürs Teilen!

eXpl0it3r

Treue Seele

Beiträge: 386

Wohnort: Schweiz

Beruf: Professional Software Engineer

  • Private Nachricht senden

4

04.07.2014, 09:29

Der Speicherbedarf ist offensichtlich genau wie bei normalen Arrays.
Um die Adresse eines Elements im N-dimensionalen Array zu bestimmen, braucht man N-1 Multiplikationen und N-1 Additionen.
Die kann man jedoch gegenüber dem eigentlichen Speicherzugriff vernachlässigen.
Mir ist schon bewusst wie es in der Theorie funktioniert, aber ob es nun auch wirklich so implementiert wurde, ist die andere Frage. Hatte jetzt nicht das Interesse den Code zu analysieren insbesondere mit all den tollen Templates Sachen. :D
Blog: https://dev.my-gate.net/
—————————————————————————
SFML: https://www.sfml-dev.org/
Thor: http://www.bromeon.ch/libraries/thor/
SFGUI: https://github.com/TankOs/SFGUI/

LukasBanana

Alter Hase

  • »LukasBanana« ist der Autor dieses Themas

Beiträge: 1 097

Beruf: Shader Tools Programmer

  • Private Nachricht senden

5

04.07.2014, 10:48

Da es sich im eigentlichen um eine einzige Datei handelt (header-only) wäre eine Datei basierende Lizenz wohl etwas mehr angebracht, z.B. MPL 2.

Ich habe mir zwar momentan nur über diese eine Klasse Gedanken gemacht, aber vielleicht kommen später noch weitere dazu.

Zitat von »eXpl0it3r«

In wiefern gibt es da einen oder eben keinen Overhead?

Wenn ich das intern mit einer Verschachtelung von Containern gemacht hätte, dann gäbe es einen gewaltigen Overhead bzgl. der Cache-Lokalität.
D.h. wenn das multi_array aus einer Liste bestehen würde, die wiederum auf Listen zeigt etc. um mehrere Dimensionen umzusetzen.

In meiner multi_array Klasse wird aber alles in ein 1-Dimensionales Array gepackt wodurch immer garantiert alles hintereinander im Speicher liegt.
Da es keine virtuelle Funktionen gibt wird auch keine v-tabel angelegt wodurch keinerlei extra Speicher angelegt wird,
auch nicht für die Länge des Arrays, im Gegensatz zu std::vector wo noch ein paar Zusatz Infos gespeichert werden.

Wenn der C++ Compiler beim std::array auch alles auf den Stack legt, könnte es sogar sein, dass in folgendem Beispiel ebenfalls kein Overhead ensteht:

C-/C++-Quelltext

1
std::array<std::array<std::array<double, 2>, 4>, 3> A;

Aber dafür ist dort die Syntax schlechter verständlich als hier:

C-/C++-Quelltext

1
multi_array<double, 3, 4, 2> A;

eXpl0it3r

Treue Seele

Beiträge: 386

Wohnort: Schweiz

Beruf: Professional Software Engineer

  • Private Nachricht senden

6

04.07.2014, 11:56

Ah okay, dann nehme ich an David's Angaben stimmen mit der Implementierung überein.

d.h. sie kann mit "std::sort", for-each Schleifen etc. benutzt werden

Wenn man nun std::sort verwendet, wie werden die Daten sortiert? Nach der Dimension oder einfach alles, egal welche Dimension?
Blog: https://dev.my-gate.net/
—————————————————————————
SFML: https://www.sfml-dev.org/
Thor: http://www.bromeon.ch/libraries/thor/
SFGUI: https://github.com/TankOs/SFGUI/

LukasBanana

Alter Hase

  • »LukasBanana« ist der Autor dieses Themas

Beiträge: 1 097

Beruf: Shader Tools Programmer

  • Private Nachricht senden

7

04.07.2014, 12:08

Das hängt von den Iteratoren ab, die "begin" und "end" zurückliefern.
Bei multi_array verweisen diese jeweils auf das gesamte Array, d.h. die Dimensions-Ebenen werden nicht einzeln sortiert.

Nur der [] Operator und die Funktion "at" beziehen sich auf die Dimensionen.
Abgesehen von ein paar weiteren Funktionen, die aber nicht zum Standard gehören, z.B. "slices".

Hat man nun ein mehr Dimensionales Array, liefert '[]' und 'at' erst mal nur eine Instance der Klasse "multi_array::slice" bzw. "...::const_slice".
Diese sind vergleichbar mit Iteratoren, die auf den Anfang der jeweiligen Slices (hier "Dimensions-Ebene") zeigen.
In aktuellen Compilern kann der Overhead, der dabei entsteht, aber vermutlich nahezu komplett weg optimiert werden (also das Erzeugen der Temporären "slice" Instanzen).

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

8

04.07.2014, 12:42

In aktuellen Compilern kann der Overhead, der dabei entsteht, aber vermutlich nahezu komplett weg optimiert werden (also das Erzeugen der Temporären "slice" Instanzen).

Am besten schaust du dir mal den generierten Assembler-Code für einen Elementzugriff array[x][y][z] an und vergleichst das mit einem normalen Array.

Beiträge: 1 223

Wohnort: Deutschland Bayern

Beruf: Schüler

  • Private Nachricht senden

9

04.07.2014, 12:54

LGPL sollte eigentlich doch die komplette Verwendung einer solchen Lib verbieten. (Außer man veröffentlicht den Source) Schließlich verbietet LGPL unteranderem statisches Linken, weil damit die Lib mit dem Programm verbunden werden und damit das Programm ein abgeleitetes Werk ist, oder so. Da die Bibliothek nur aus einem Header besteht, werden automatisch alle Datenstrukturen und Algorithmen direkt in die Binary hinein gelinkt und es müsste das doch ebenfalls die Bedingungen der LGPL fallen, so das man seine Anwendung mit Quellcode veröffentlichen muss? Das wären meine Gedanken. Kann auch sein das ich falsch liege.

Ich persönlich würde LGPL Software in aller Regel nicht verwenden. An deiner Stelle würde ich über eine andere Lizenz nachdenken. (L)GPL ist meiner Ansicht schlecht für Softwarebibliotheken geeignet, ganz besonders wenig für "Grundlagenbibliotheken". Es gibt ja genug weniger restriktive Alternativen: BSD, MIT oder zLib zum Beispiel...

EDIT:
Ich würde auch empfehlen, dass du mal Davids Vorschlag anwendest. Ein Arrayzugriff sollte keinen unnötigen Overhead mitbringen. Schließlich das häufig der Flaschenhals in inneren Schleifen. Auch relastische Benchmarks bei der Iteration darüber wären interessant.

Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von »Spiele Programmierer« (04.07.2014, 13:14)


eXpl0it3r

Treue Seele

Beiträge: 386

Wohnort: Schweiz

Beruf: Professional Software Engineer

  • Private Nachricht senden

10

04.07.2014, 13:09

LGPL sollte eigentlich doch die komplette Verwendung einer solchen Lib verbieten. (Außer man verwendet selbst LGPL) Schließlich verbietet LGPL unteranderem statisches Linken, weil damit die Lib mit dem Programm verbunden werden und damit das Programm ein abgeleitetes Werk ist, oder so. Da die Bibliothek nur aus einem Header besteht, werden automatisch alle Datenstrukturen und Algorithmen direkt in die Binary hinein gelinkt und es müsste das doch ebenfalls die Bedingungen der LGPL fallen, so das man seine Anwendung mit Quellcode veröffentlichen muss? Das wären meine Gedanken. Kann auch sein das ich falsch liege.
Hatte ich zuerst auch gedacht, hab dann aber mal Google gefragt (stell dir vor gewisse Leute machen das noch!) und es scheint okay zu sein. ;)
Blog: https://dev.my-gate.net/
—————————————————————————
SFML: https://www.sfml-dev.org/
Thor: http://www.bromeon.ch/libraries/thor/
SFGUI: https://github.com/TankOs/SFGUI/

Werbeanzeige