Python 3.14 นำโมดูล concurrent.interpreters เพิ่มความเร็ว
ทดสอบโมดูล subinterpreters ใหม่ใน Python 3.14 ช่วยลดคอขวด GIL จาก 3.6 วินาทีเหลือ 0.9 วินาที พร้อมเผยข้อจำกัดการใช้งานและการเปลี่ยนค่าเริ่มต้นบน Linux

ภาพประกอบจากคลังภาพสต็อก ไม่ใช่ภาพจากเหตุการณ์จริง
- Python 3.14 เพิ่มโมดูล concurrent.interpreters ในไลบรารีมาตรฐาน
- ช่วยลดเวลาประมวลผลงาน CPU-bound จาก 3.6 วินาทีเหลือ 0.9 วินาที
- ตัวแปลภาษาแต่ละตัวมี GIL แยกอิสระ แต่ไม่อนุญาตให้รันพร้อมกันหลายงานในตัวเดียว
- Linux ใน Python 3.14 เปลี่ยนค่าเริ่มต้น multiprocessing จาก fork เป็น forkserver
การอัปเดตครั้งสำคัญใน Python 3.14 ที่เปิดตัวเมื่อวันที่ 7 ตุลาคม 2026 ได้นำโมดูล concurrent.interpreters เข้ามาในไลบรารีมาตรฐาน แม้ว่าระบบย่อยอย่าง subinterpreters จะมีมานานแล้วใน C API ตั้งแต่เวอร์ชัน 1.5 แต่ PEP 734 คือจุดเปลี่ยนที่ทำให้โค้ด Python ทั่วไปสามารถเรียกใช้งานได้โดยตรงโดยไม่ต้องอาศัย C extension ทำให้งานประมวลผลหนักๆ บนซีพียูสามารถใช้ประโยชน์จากหลายแกนประมวลผลได้จริงโดยไม่ต้องพึ่งพาระบบ multiprocessing
จากการทดสอบงานประมวลผลหนักๆ อย่างการนับจำนวนเฉพาะที่ต่ำกว่า 400,000 ภายในคอนเทนเนอร์ python:3.14-slim ที่มี 4 แกนประมวลผล พบว่าการใช้เธรดแบบคลาสสิก 4 เธรดใช้เวลาถึง 3.51 - 3.70 วินาที เนื่องจากติดปัญหาคอขวดของ Global Interpreter Lock (GIL) ที่ต้องสลับกันทำงาน แต่เมื่อเปลี่ยนมาใช้ subinterpreters จำนวน 4 ตัว เวลาลดลงเหลือเพียง 0.89 - 0.98 วินาที ซึ่งใกล้เคียงกับการทำงานแบบเธรดเดี่ยว

ภาพประกอบจากคลังภาพสต็อก ไม่ใช่ภาพจากเหตุการณ์จริง
อย่างไรก็ตาม โมดูลนี้มีข้อจำกัดที่น่าสนใจคือ อินสแตนซ์ของ Interpreter หนึ่งตัวจะยอมรับผู้เรียกใช้งานได้เพียงหนึ่งงานเท่านั้น หากมีการเรียกใช้งานพร้อมกันเป็นครั้งที่สอง ระบบจะไม่เข้าคิวรอแต่จะปฏิเสธในทันทีโดยการส่งข้อผิดพลาด InterpreterError ออกมา ดังตัวอย่างข้อความความผิดพลาดที่เกิดขึ้น:
"Exception in thread Thread-2 (_call)... concurrent.interpreters.InterpreterError: interpreter already running"
Traceback Error
การทำความเข้าใจสถาปัตยกรรม subinterpreters ใน Python 3.14 ช่วยให้เห็นภาพว่า การออกแบบนี้มุ่งเน้นการแยกสถานะออกจากกันอย่างเด็ดขาดเพื่อหลีกเลี่ยงปัญหาความซับซ้อนของหน่วยความจำร่วม (Shared Memory) แม้ว่านักพัฒนาคุ้นเคยกับการใช้ ThreadPoolExecutor ที่ให้หลายเธรดวิ่งเข้าหาตัวจัดการเดียว แต่แนวทางนี้ใช้ไม่ได้กับ subinterpreters ที่ต้องสร้างตัวจัดการใหม่แบบหนึ่งต่อหนึ่งเท่านั้น
ในด้านการจัดการหน่วยความจำและการส่งผ่านข้อมูล ข้อมูลพื้นฐานเช่น int, str, bytes, bool และ float สามารถส่งผ่านได้โดยตรงผ่านฟังก์ชัน is_shareable() แต่ข้อมูลประเภท list หรือ dict ไม่รองรับการส่งผ่านโดยตรง เว้นแต่จะใช้ Queue ข้ามอินเทอร์เฟซที่จะทำการ pickle และ unpickle ข้อมูลให้อัตโนมัติ นอกจากนี้ บนระบบปฏิบัติการ Linux ใน Python 3.14 ยังมีการเปลี่ยนวิธีการเริ่มต้นกระบวนการทำงานจาก fork ไปเป็น forkserver เป็นค่าเริ่มต้น ซึ่งนักพัฒนาต้องระวังการเขียนโค้ดที่ไม่มีการป้องกันด้วยเงื่อนไข if __name__ == "__main__": มิฉะนั้นจะเกิดข้อผิดพลาดในการบูตกระบวนการทำงานทันที
ที่มา: Dev.to
พบข้อมูลผิดพลาดในบทความนี้? แจ้งปัญหาบทความนี้
ความคิดเห็น
แสดงความคิดเห็น