ขนาดสแต็กเริ่มต้นสำหรับ pthreads


24

ดังที่ฉันเข้าใจขนาดสแต็คเริ่มต้นสำหรับ pthread บน Linux คือ 16K ฉันได้รับผลลัพธ์ที่แปลกในการติดตั้ง Ubuntu แบบ 64 บิตของฉัน

$ ulimit -s
8192

นอกจากนี้:

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

Prints
    Thread stack size = 8388608 bytes

ฉันค่อนข้างแน่ใจว่าขนาดสแต็กไม่ใช่ "8388608" มีอะไรผิดปกติ?


7
8388608 / 1024 = 8192ผมคิดว่า
cuonglm

6
คุณคิดว่าการ16k ต่อด้ายเคอร์เนลกอง แยกปัญหาโดยสิ้นเชิงจากหน่วยความจำสแต็กพื้นที่ผู้ใช้ เคอร์เนลสแต็คมีขนาดเล็กเนื่องจากไม่สามารถทำเพจจิ้งหรือถูกจัดสรรแบบสันหลังยาวและต้องเป็นเพจที่ต่อเนื่องกันในหน่วยความจำกายภาพ elinux.org/Kernel_Small_Stacks การมีจำนวนเธรดทั้งหมดที่สูงมากอาจเป็นปัญหาสำหรับ i386 ซึ่งพื้นที่ที่อยู่ถูก จำกัด โดยเฉพาะกับ 8k สแต็คโดยค่าเริ่มต้นสำหรับ 32 บิต
Peter Cordes

คำตอบ:


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

stacksizeแอตทริบิวต์จะกำหนดขนาดต่ำสุดสแต็ค (ไบต์) จัดสรรสำหรับสร้างหัวข้อสแต็ค

ในตัวอย่างของคุณขนาดสแต็กถูกตั้งค่าเป็น 8388608 ไบต์ซึ่งสอดคล้องกับ 8MB ตามที่ส่งคืนโดยคำสั่งulimit -s ดังนั้นจึงตรงกับ

จากpthread_create()คำอธิบาย:

บนลินุกซ์ / x86-32ขนาดสแต็คเริ่มต้นสำหรับหัวข้อใหม่คือ2 เมกะไบต์ ภายใต้การนำไปใช้การเธรด NPTL ถ้า ขีด จำกัด ซอฟต์รีซอร์สRLIMIT_STACKณ เวลาที่โปรแกรมเริ่มทำงานมีค่าอื่นนอกเหนือจาก "unlimited" ดังนั้นจะกำหนดขนาดสแต็กเริ่มต้นของเธรดใหม่ การใช้pthread_attr_setstacksize (3) แอ็ตทริบิวต์ขนาดสแต็กสามารถตั้งค่าได้อย่างชัดเจนในอาร์กิวเมนต์ attr ที่ใช้เพื่อสร้างเธรดเพื่อรับขนาดสแต็กอื่นที่ไม่ใช่ค่าดีฟอลต์

ดังนั้นขนาดด้ายสแต็กสามารถตั้งค่าได้ผ่านฟังก์ชั่นการตั้งค่าด้านบนหรือulimitคุณสมบัติของระบบ สำหรับ 16k ที่คุณอ้างถึงยังไม่ชัดเจนว่าแพลตฟอร์มใดที่คุณเคยเห็นและ / หรือหากมีการตั้งค่าขีด จำกัด ของระบบสำหรับสิ่งนี้

ดูหน้า pthread_createและที่นี่สำหรับตัวอย่างที่น่าสนใจเกี่ยวกับเรื่องนี้


47

ที่จริงแล้วขนาดสแต็กเสมือนของคุณคือ 8388608 ไบต์ (8 MB) แน่นอนว่าเป็นเรื่องธรรมดาที่จะสรุปได้ว่านี่ไม่ถูกต้องเพราะนั่นเป็นหน่วยความจำจำนวนมากสำหรับทุกเธรดที่ใช้งานสแต็กเมื่อ 99% ของเวลา KB สองเท่าน่าจะเป็นสิ่งที่พวกเขาต้องการ

ข่าวดีก็คือที่เธรดของคุณใช้จำนวนหน่วยความจำกายภาพที่ต้องการเท่านั้น นี่คือหนึ่งในพลังวิเศษที่ระบบปฏิบัติการของคุณได้รับจากการใช้หน่วยความจำฮาร์ดแวร์การจัดการหน่วย (MMU) ในโปรเซสเซอร์ของคุณ นี่คือสิ่งที่เกิดขึ้น:

  1. ระบบปฏิบัติการจัดสรรหน่วยความจำเสมือน 8 MB สำหรับสแต็กของคุณโดยตั้งค่าตารางหน้าของ MMU สำหรับเธรดของคุณ ต้องใช้ RAM น้อยมากในการเก็บรายการตารางหน้าเท่านั้น

  2. เมื่อเธรดของคุณรันและพยายามเข้าถึงที่อยู่เสมือนบนสแต็กที่ยังไม่มีหน้าทางกายภาพกำหนดให้ข้อยกเว้นฮาร์ดแวร์ที่เรียกว่า "page fault" ถูกเรียกใช้โดย MMU

  3. ซีพียูหลักตอบสนองต่อข้อผิดพลาดของเพจข้อผิดพลาดโดยเปลี่ยนไปใช้โหมดการเรียกใช้สิทธิพิเศษ (ซึ่งมีสแต็กของตัวเอง) และการเรียกฟังก์ชันตัวจัดการข้อยกเว้นความผิดพลาดหน้าภายในเคอร์เนล

  4. เคอร์เนลจัดสรรหน้า RAM จริงไปยังหน้าหน่วยความจำเสมือนนั้นและส่งคืนกลับไปยังเธรดพื้นที่ผู้ใช้

เธรดพื้นที่ผู้ใช้ไม่เห็นงานใด ๆ จากมุมมองของมันเพียงใช้สแต็คราวกับว่ามีหน่วยความจำตลอด ในขณะเดียวกันสแต็กจะโตขึ้น (หรือไม่) โดยอัตโนมัติเพื่อตอบสนองความต้องการของเธรด

MMU เป็นส่วนสำคัญของฮาร์ดแวร์ของระบบคอมพิวเตอร์ในปัจจุบัน โดยเฉพาะอย่างยิ่งมันรับผิดชอบ "มายากล" จำนวนมากในระบบดังนั้นฉันขอแนะนำให้เรียนรู้เพิ่มเติมเกี่ยวกับสิ่งที่ MMU ทำและเกี่ยวกับหน่วยความจำเสมือนโดยทั่วไป นอกจากนี้หากแอปพลิเคชันของคุณมีความไวต่อประสิทธิภาพและเกี่ยวข้องกับข้อมูลจำนวนมากคุณควรเข้าใจว่า TLB (แคชตารางหน้าของ MMU) ทำงานอย่างไรและคุณสามารถปรับโครงสร้างข้อมูลหรืออัลกอริทึมของคุณอย่างไรเพื่อเพิ่มอัตราการตี TLB ให้สูงสุด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.