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

Evrey

Treue Seele

  • »Evrey« ist der Autor dieses Themas

Beiträge: 245

Beruf: Weltherrscher

  • Private Nachricht senden

1

04.06.2014, 20:49

posix_memalign / _aligned_malloc

Ave, Plebs. °^°
Ich bastle gerade aus Langeweile und Neugier einen Pool-Allocator, der mit ähnlichen Hacks wie der geplante GC von LuaJIT arbeitet. Das heißt im Klartext: Ich frage das Betriebssystem nach einem ziiiemlich großen Speicherblock, dessen Größe 2MiB oder 4MiB beträgt. (Abhängig von sizeof(void*).) Die Pools sollen dabei auf ihre Größe hin aligned sein. Bei 1MiB also wären die untersten 20bit der Adresse 0. Ich habe zunächst einfach mal mit ::mmap und ::VirtualAlloc nach Speicher gefragt, doch bekam nicht das, was ich wollte, nämlich das Alignment.
Dann hatte ich die Überschrift ausprobiert. Klasse, ich bekam genau mein Alignment! Allerdings zu einem Preis, den ich befürchtet hatte: Die Implementierung reserviert mal eben den doppelten Speicher, um unliebsame Bereiche wegzuschmeißen. Das wäre zwar im Interesse des hacky Codes, allerdings nicht im Interesse des hypothetischen Nutzers eines solchen Allocators.

Meine Frage an der Stelle wäre also, ob ihr schonendere Möglichkeiten kennt, solche Speicher-Bedürfnisse zu decken. Ich recherchiere mir da gerade ziemlich einen Ast ab, aber derartige Fragen findet man nicht oft... =D"

Gruß und Segen,
Evrey

C-/C++-Quelltext

1
2
3
4
int main(int _argc, char** _argv) noexcept {
  asm volatile("lock cmpxchg8b %eax");
  return 0;
} // ::main
(Dieses kleine Biest vermochte einst x86-Prozessoren lahm zu legen.)

=> Und er blogt unter Hackish.Codes D:

Legend

Alter Hase

Beiträge: 731

Beruf: Softwareentwickler

  • Private Nachricht senden

2

04.06.2014, 21:19

Du könntest mit VirtualAlloc den doppelten Speicher allokieren und mit VirtualFree unliebsame Teile wieder freigeben.
"Wir müssen uns auf unsere Kernkompetenzen konzentrieren!" - "Juhu, wir machen eine Farm auf!"

Netzwerkbibliothek von mir, C#, LGPL: https://sourceforge.net/projects/statetransmitt/

Evrey

Treue Seele

  • »Evrey« ist der Autor dieses Themas

Beiträge: 245

Beruf: Weltherrscher

  • Private Nachricht senden

3

04.06.2014, 21:29

Ach, das geht? ö.ö Direkt mal testen, danke.

C-/C++-Quelltext

1
2
3
4
int main(int _argc, char** _argv) noexcept {
  asm volatile("lock cmpxchg8b %eax");
  return 0;
} // ::main
(Dieses kleine Biest vermochte einst x86-Prozessoren lahm zu legen.)

=> Und er blogt unter Hackish.Codes D:

Legend

Alter Hase

Beiträge: 731

Beruf: Softwareentwickler

  • Private Nachricht senden

4

04.06.2014, 21:50

Hmm, auf einen zweiten Blick kann man so nur Speicher decommiten, aber nicht freigeben. :/
"Wir müssen uns auf unsere Kernkompetenzen konzentrieren!" - "Juhu, wir machen eine Farm auf!"

Netzwerkbibliothek von mir, C#, LGPL: https://sourceforge.net/projects/statetransmitt/

Evrey

Treue Seele

  • »Evrey« ist der Autor dieses Themas

Beiträge: 245

Beruf: Weltherrscher

  • Private Nachricht senden

5

04.06.2014, 22:09

Meh... D: Dann bleib ich erstmal bei diesem Spaß, bis ich die Erleuchtung finde oder jemand hier zufällig die Antwort kennt. Danke jedenfalls. °^°

C-/C++-Quelltext

1
2
3
4
int main(int _argc, char** _argv) noexcept {
  asm volatile("lock cmpxchg8b %eax");
  return 0;
} // ::main
(Dieses kleine Biest vermochte einst x86-Prozessoren lahm zu legen.)

=> Und er blogt unter Hackish.Codes D:

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Evrey« (04.06.2014, 22:37)


6

05.06.2014, 09:56

Win32 hat eine Allocation Granularity von 64 KiB; grundsätzlich sind also alle deine frischen Allokationen daran ausgerichtet. Normalerweise reicht das auch aus ;)

Du kannst VirtualAlloc eine Adresse übergeben, an der du reservieren möchtest. Ganz naiv würdest du also in 1-MiB-Schritten über den Adressraum gehen, bei jedem Schritt via VirtualQuery prüfen, ob der Block dort allokiert ist, und falls nicht, VirtualAlloc mit dieser Adresse aufrufen. Das kannst du dann optimieren indem du Liste über die Blöcke führst.

Bedenk, dass man den Freispeicher normalerweise am dem Stapel gegenüberliegenden Ende des Adressraums platziert und dass DLLs in der Mitte liegen und dass einige Bereiche des Adressraums reserviert sind. Bedenk außerdem, dass bei /LARGEADRESSAWARE Integer-Über- und -Unterläufe auftreten können.

Beiträge: 1 223

Wohnort: Deutschland Bayern

Beruf: Schüler

  • Private Nachricht senden

7

05.06.2014, 13:29

Also wenn man "VirtualFree" "MEM_RELEASE" übergibt, sieht es für mich so aus, als ob man damit den Speicher freigeben kann. So habe ich das jedenfalls bisher gehandhabt und scheint mir Sinn zu machen.

Es gibt einen ganz gewaltigen Unterschied zwischen "_aligned_malloc" etc wie im Titel steht und "Virtual*" und co.
Mit der zweiten Funktion kannst du direkt Paging steuern und anfordern.
Die erstere Funktion kann dies nicht und hat einen zusätzlichen Zwischenlayer, um nicht bloß komplette Pages(bzw. bei Windows eben sogar 64KB) anzufordern sondern auch kleinere Allokationen effizient zu handeln. Irgendwo her müssen Funktionen wie "_aligned_malloc" ja auch ihren Speicher bekommen, und das machen sie unter dieser Verwaltungsschicht mit hoher Wahrscheinlichkeit direkt mit "VirtualAlloc" usw.
Ich habe auch gelesen, dass das die Allokationen beim MSVC ab einer gewissen Größe direkt an entsprechende "VirtualAlloc" weitergeleitet werden.
Wenn du selber einen Speicherallokator entwickelst, wäre es meiner Ansicht nach wesentlich sinnvoller, direkt mit den "Virtual*" zu steuern, was wirklich passieren soll. Die sind dann auch automatisch aligned.

8

05.06.2014, 14:07

Ich habe auch gelesen, dass das die Allokationen beim MSVC ab einer gewissen Größe direkt an entsprechende "VirtualAlloc" weitergeleitet werden.
Ja; die Grenze lag wohl zwischen 512 KiB und 4 MiB. Es ist aber keine direkte Weiterleitung im Wortsinne sondern zusätzlicher Overhead damit die Seiten auch wieder freigegeben werden wenn man den übergeordneten Heap freigibt. Auf jeden Fall ist es aber für die meisten Anwendungsfälle eine deutlich besser durchdachte und leistungsfähigere Lösung als was Selbstgebasteltes.

Evrey

Treue Seele

  • »Evrey« ist der Autor dieses Themas

Beiträge: 245

Beruf: Weltherrscher

  • Private Nachricht senden

9

05.06.2014, 14:58

Zitat

Win32 hat eine Allocation Granularity von 64 KiB;
Jah, das hab ich auch festgestellt. Allerdings hätt ich wie gesagt gern ein Alignment der Größe der Arenas, da andernfalls die ganzen schönen Hacks nicht machbar sind.

Zitat

Also wenn man "VirtualFree" "MEM_RELEASE" übergibt, sieht es für mich so aus, als ob man damit den Speicher freigeben kann.
Dann werde ich das heute abend mal ausprobieren, ob ich unbenutzten Quark wieder freigeben kann, also z.B. 4MiB reserviere, auf 2MiB aligne, und die überflüssigen 2MiB am Anfang und Ende wieder frei gebe. (Wie umständlich...) Ich frage mich, warum _aligned_malloc das nicht von Haus aus tut. ôO

Ansonsten wäre meine Notlösung, die ich nicht gern einsetzen möchte, dass ich auf Anhieb 15 Arenas reserviere, so dass "nur" 1/15 des reservierten Speichers verschwendet wird, was mir noch immer 1/15 zu viel ist. Bei 2MiB / 4MiB Arenas.

C-/C++-Quelltext

1
2
3
4
int main(int _argc, char** _argv) noexcept {
  asm volatile("lock cmpxchg8b %eax");
  return 0;
} // ::main
(Dieses kleine Biest vermochte einst x86-Prozessoren lahm zu legen.)

=> Und er blogt unter Hackish.Codes D:

10

05.06.2014, 15:20

Zitat

Ich frage mich, warum _aligned_malloc das nicht von Haus aus tut. ôO
Weil 99,9 % der Anwendungsfälle nur Ausrichtung auf 8 oder 16 B brauchen, und es bei denen nicht ins Gewicht fällt. Es würde mich wundern, wenn sie Ausrichtung > 4096 beim Entwurf überhaupt bedacht haben – braucht schließlich nie jemand.

Und zu guter Letzt gehe ich davon aus, dass sie für Debug-Versionen die Größe des Speicherblocks in die ersten Bytes schreiben; dann wuchert der Block ebenfalls ganz gewaltig.

Werbeanzeige