1 คะแนน โดย GN⁺ 2023-10-08 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • บทความนี้กล่าวถึงข้อถกเถียงในชุมชน Rust เกี่ยวกับการใช้งานตัวดำเนินการแบบหลายเธรด ซึ่งเป็น async runtime ที่ทำ work-stealing เพื่อกระจายงานอย่างสมดุล
  • ผู้ใช้ Rust บางส่วนเสนอแนวทางสถาปัตยกรรมทางเลือกที่เรียกว่า "thread-per-core" โดยให้เหตุผลว่าน่าจะให้ประสิทธิภาพดีกว่าและติดตั้งใช้งานได้ง่ายกว่า
  • คำว่า "thread-per-core" อาจทำให้เข้าใจผิดได้ เพราะตัวดำเนินการแบบหลายเธรดทุกตัวก็เป็น thread-per-core อยู่แล้ว โดยสร้าง OS thread หนึ่งตัวต่อหนึ่งคอร์ และจัดตารางงานบนเธรดเหล่านั้น
  • Thread-per-core เป็นการผสาน 3 แนวคิดเข้าด้วยกัน: การจัดการ concurrency ใน user space, ทำให้ I/O เป็น asynchronous เพื่อหลีกเลี่ยงการบล็อกเธรด, และแบ่งข้อมูลตาม CPU core เพื่อตัดต้นทุนการ synchronization และการย้ายข้อมูลระหว่าง CPU cache
  • ข้อถกเถียงนี้มุ่งไปที่ประเด็นที่สามเป็นหลัก และการใช้ async Rust ก็สามารถตอบโจทย์สองข้อแรกได้
  • ในสถาปัตยกรรม thread-per-core สามารถทำ optimization ได้สองแบบ: ขโมยงานระหว่างเธรด และแชร์สถานะให้น้อยที่สุดเท่าที่ทำได้
  • Work-stealing ช่วยให้ทุกเธรดมีงานทำอยู่เสมอ จึงช่วยปรับปรุง tail latency แต่ทำได้ยากในการติดตั้งใช้งาน และอาจทำให้เกิดต้นทุนจากการ synchronization กับ cache miss
  • Share-nothing ช่วยปรับปรุง tail latency โดยคงข้อมูลไว้ใน cache ที่เร็วกว่าและเป็นของ CPU core เดียว แต่ก็อาจติดตั้งใช้งานได้ยากสำหรับแอปพลิเคชันที่ซับซ้อนซึ่งต้องเปลี่ยนสถานะในหลายพาร์ทิชัน
  • บทความนี้เสนอว่าในระบบที่ใช้ shared state นั้น work-stealing อาจช่วยเพิ่มการใช้ CPU ภายใต้โหลดได้

1 ความคิดเห็น

 
GN⁺ 2023-10-08
ความคิดเห็นจาก Hacker News
  • ประเด็นหลักของข้อถกเถียงไม่ใช่เรื่องตัวทำงานแบบขโมยงานต่อคอร์ (executors) แต่เป็นเรื่องที่ว่า async/await ใน Rust เป็น abstraction ที่ดีหรือไม่
  • แนวคิดเธรดต่อคอร์ถูกคิดค้นขึ้นเพื่อแก้ปัญหาความสามารถในการขยายตัวและประสิทธิภาพของการประมวลผลบนเซิร์ฟเวอร์แบบหลายคอร์ทั่วไป และพบว่ามันยอดเยี่ยมมากสำหรับงาน I/O-bound ที่มี throughput สูง
  • สถาปัตยกรรมเธรดต่อคอร์จะยังคงอยู่ต่อไปเพราะความสามารถในการขยายตัวและประสิทธิภาพของมัน แต่โดยมากแล้ววิศวกรซอฟต์แวร์ยังมีสัญชาตญาณที่จำกัดเกี่ยวกับหน้าตาของการออกแบบเธรดต่อคอร์แบบสมัยใหม่และเป็นไปตามแนวปฏิบัติทั่วไป
  • แอปพลิเคชันบางประเภทเหมาะกับระบบเธรดเดี่ยวมากกว่า และ Rust ก็รองรับความยืดหยุ่นแบบนั้น
  • มีคำวิจารณ์ต่อการเขียนโปรแกรมแบบ async ของ Rust ซึ่งรวมถึงการที่ต้องการ Send + Sync + 'static และบางคนมองว่านี่เป็นภาระ
  • ข้อกำหนด Send เป็นเงื่อนไขที่อนุญาตให้ย้ายงานระหว่างเธรดของ executor ได้ ซึ่งดูเหมือนจะเป็นข้อบกพร่องของระบบ async ใน Rust
  • ไม่มีแนวทางแบบเหมารวมที่ให้ประสิทธิภาพดีที่สุดกับทุกโปรแกรม และการใช้ async ก็ถูกมองว่าเป็นการเพิ่มประสิทธิภาพก่อนเวลาอันควรสำหรับโปรแกรม Rust จำนวนมาก
  • เนื่องจากการสลับคอนเท็กซ์ของเคอร์เนลมีต้นทุนสูง จึงมีแนวโน้มจะชอบการออกแบบแบบเธรดต่อคอร์ แต่การจัดตารางด้วยการสลับคอนเท็กซ์ใน user space ก็อาจเป็นปัญหาได้เช่นกัน
  • การขโมยงานเป็นวิธีหนึ่งในการแก้ปัญหา tail latency แต่ก็ก่อให้เกิด cache miss และข้อจำกัดเพิ่มเติมสำหรับนักพัฒนา เช่น Send, Sync และ ‘static