Standardstapelgröße für Pthreads

24

Soweit ich weiß, beträgt die Standardstapelgröße für einen pthread unter Linux 16 KB. Ich erhalte merkwürdige Ergebnisse bei meiner 64-Bit-Ubuntu-Installation.

$ ulimit -s
8192

Ebenfalls:

pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &stacksize);
printf("Thread stack size = %d bytes \n", stacksize);

Prints
    Thread stack size = 8388608 bytes

Ich bin mir ziemlich sicher, dass die Stapelgröße nicht "8388608" ist. Was könnte falsch sein?

Kamath
quelle
7
Ich denke 8388608 / 1024 = 8192.
Donnerstag,
6
Sie denken an 16k pro Thread- Kernel- Stapel . Völlig getrenntes Problem vom User-Space-Stack-Speicher. Kernel-Stacks sind winzig, weil sie nicht ausgelagert oder faul zugeordnet werden können und zusammenhängende Seiten im physischen Speicher sein müssen. elinux.org/Kernel_Small_Stacks . Eine extrem hohe Anzahl an Gesamt-Threads kann ein Problem für i386 sein, bei dem der Adressraum begrenzt ist, insbesondere bei 8-KB-Stacks für 32-Bit-Threads.
Peter Cordes

Antworten:

21
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);

Das stacksizeAttribut definiert die minimale Stapelgröße (in Bytes), die dem erstellten Thread-Stapel zugewiesen wird.

In Ihrem Beispiel ist die Stack-Größe auf 8388608 Bytes festgelegt, was 8 MB entspricht, wie vom entsprechenden Befehl zurückgegeben ulimit -s .

Aus der pthread_create()Beschreibung:

Unter Linux / x86-32 beträgt die Standardstapelgröße für einen neuen Thread 2 Megabyte . Wenn bei der NPTL-Threading-Implementierung das RLIMIT_STACK- Limit für weiche Ressourcen zum Zeitpunkt des Programmstarts einen anderen Wert als "unbegrenzt" hat, wird die Standardstapelgröße neuer Threads bestimmt. Mit pthread_attr_setstacksize (3) kann das Attribut stack size im Argument attr, das zum Erstellen eines Threads verwendet wird, explizit festgelegt werden, um eine andere als die Standardstapelgröße zu erhalten.

Die Thread-Stack-Größe kann also entweder über die oben angegebene Set-Funktion oder über die ulimitSystemeigenschaft festgelegt werden. Für die 16k, auf die Sie sich beziehen, ist nicht klar, auf welcher Plattform Sie das gesehen haben und / oder ob dafür ein Systemlimit festgelegt wurde.

Auf der Seite pthread_create und hier finden Sie einige interessante Beispiele dazu.

fduff
quelle
47

Eigentlich Ihre virtuelle Stack - Größe ist 8388608 Bytes (8 MB). Natürlich kann man zu dem Schluss kommen, dass dies nicht richtig sein kann, da dies eine lächerlich große Menge an Speicher für jeden Thread ist, der für seinen Stapel verbraucht wird, wenn in 99% der Fälle wahrscheinlich nur ein paar KB erforderlich sind.

Die gute Nachricht ist, dass Ihr Thread nur die Menge an physischem Speicher verwendet, die er tatsächlich benötigt. Dies ist eine der magischen Kräfte, die Ihr Betriebssystem durch die Verwendung der Hardware Memory Management Unit (MMU) in Ihrem Prozessor erhält. Folgendes passiert:

  1. Das Betriebssystem weist Ihrem Stapel 8 MB virtuellen Speicher zu, indem es die Seitentabellen der MMU für Ihren Thread erstellt. Dies erfordert sehr wenig RAM, um nur die Seitentabelleneinträge aufzunehmen.

  2. Wenn Ihr Thread ausgeführt wird und versucht, auf eine virtuelle Adresse auf dem Stapel zuzugreifen, der noch keine physische Seite zugewiesen ist, wird von der MMU eine Hardwareausnahme ausgelöst, die als "Seitenfehler" bezeichnet wird.

  3. Der CPU-Kern reagiert auf die Ausnahmebedingung für Seitenfehler, indem er in einen privilegierten Ausführungsmodus (der über einen eigenen Stapel verfügt) wechselt und die Ausnahmebehandlungsfunktion für Seitenfehler im Kernel aufruft.

  4. Der Kernel weist dieser virtuellen Speicherseite eine Seite mit physischem RAM zu und kehrt zum Benutzerbereichsthread zurück.

Der User Space Thread sieht nichts davon. Aus seiner Sicht verwendet es den Stack einfach so, als ob der Speicher die ganze Zeit da wäre. In der Zwischenzeit wird der Stapel automatisch vergrößert (oder nicht vergrößert), um die Anforderungen des Threads zu erfüllen.

Die MMU ist ein wesentlicher Bestandteil der Hardware heutiger Computersysteme. Insbesondere ist es für einen Großteil der "Magie" im System verantwortlich. Daher empfehle ich dringend, mehr über die Funktionsweise der MMU und den virtuellen Speicher im Allgemeinen zu erfahren. Wenn Ihre Anwendung leistungsabhängig ist und eine erhebliche Datenmenge verarbeitet, sollten Sie wissen, wie der TLB (der Seitentabellencache der MMU) funktioniert und wie Sie Ihre Daten oder Algorithmen umstrukturieren können, um Ihre TLB-Trefferrate zu maximieren.

jtchitty
quelle