- หลังจาก Python Steering Council แสดงเจตนารับ PEP 703 การนำ GIL ออกจาก CPython ก็เข้าสู่กระบวนการเปลี่ยนผ่านแบบค่อยเป็นค่อยไปยาวนาน ตั้งแต่บิลด์เชิงทดลองไปจนถึงการสลับเป็นโหมดค่าเริ่มต้น
- การนำ GIL ออกอาจเปิดทางให้ประสิทธิภาพแบบหลายเธรดดีขึ้น แต่ก็อาจมีต้นทุนต่อ ประสิทธิภาพแบบเธรดเดียว ซึ่งครองสัดส่วนหลักของระบบนิเวศเดิม และต่อความเข้ากันได้ของ C extension
- ทีม Faster CPython มองว่า interpreter แบบ adaptive specialization ที่อิง PEP 659 พึ่งพา GIL อยู่ ดังนั้นในสภาพแวดล้อม no-GIL จึงต้องคำนวณกลยุทธ์การเพิ่มประสิทธิภาพและภาระการบำรุงรักษาใหม่
- Meta ระบุว่าหาก PEP 703 ได้รับการยอมรับ จะทุ่ม 3 engineer-years ภายในสิ้นปี 2025 และ Anaconda ก็ให้คำมั่นว่าจะช่วยงานด้านแพ็กเกจจิง เช่น pip, cibuildwheel และ conda-forge
- การเปลี่ยนผ่านจะเดินไปในทิศทางที่หลีกเลี่ยงความแตกหักแบบ Python 2→3 และหากเห็นว่าความสับสนจาก no-GIL มีมากกว่าประโยชน์ ก็ยังสามารถถอนกลับได้ก่อนประกาศให้เป็นโหมดค่าเริ่มต้น
การถกเถียงเรื่องการนำ GIL ออกจาก Python กลับมาเข้มข้นอีกครั้ง
- Global Interpreter Lock (GIL) ของ Python ทำหน้าที่ทำให้การเข้าถึง virtual machine ของ interpreter เป็นแบบอนุกรม เพื่อให้มีเพียงหนึ่งเธรดที่รันโค้ด Python ได้ในแต่ละครั้ง
- GIL ซึ่งขัดขวางการเพิ่มประสิทธิภาพด้วยหลายเธรด ถูกพูดถึงมานานในฐานะจุดอ่อนเก่าแก่ของ Python
- Sam Gross เปิดเผย เวอร์ชันพิสูจน์แนวคิดของ no-GIL Python ในเดือนตุลาคม 2021 และหลังความสนใจระยะแรก ความคืบหน้าก็มีจำกัดอยู่กว่าหนึ่งปี
- หลังจากนั้น Python Steering Council ก็ประกาศ ความตั้งใจที่จะรับฟีเจอร์ no-GIL
- กว่าจะเข้าไปอยู่ในเวอร์ชันรีลีสจริงยังต้องใช้เวลา
- ยังมีความเป็นไปได้ที่งานนี้จะถูกย้อนกลับในอนาคต
- การสนับสนุนจากหลายบริษัททำให้โอกาสสำเร็จสูงขึ้น
ความตึงเครียดระหว่าง Faster CPython กับประสิทธิภาพแบบเธรดเดียว
- ในงาน Python Language Summit ปี 2022 Gross นำเสนอ no-GIL fork โดยพยายามขอฉันทามติโดยนัยต่อการเดินหน้างานนี้ แต่ยังไม่เกิดข้อสรุป เพราะผลกระทบในรายละเอียดเป็นที่เข้าใจไม่มากพอ
- ในช่วงเดียวกัน โครงการ Faster CPython ก็กำลังมุ่งเน้นการยกระดับประสิทธิภาพแบบเธรดเดียวของ interpreter
- Mark Shannon เขียน PEP 659 “Specialized Adaptive Interpreter” และบางส่วนของการเปลี่ยนแปลงนี้ได้เข้าไปอยู่ใน Python 3.10 และ 3.11
- ในงาน PyCon ทาง Brandt Bucher จากทีม Faster CPython ได้นำเสนอเรื่องคำสั่งแบบ adaptive ส่วน Shannon นำเสนอการปรับปรุง memory layout และเทคนิค optimization อื่น ๆ
- เนื่องจากโปรแกรม Python เดิมเกือบทั้งหมดถูกเขียนให้ทำงานแบบเธรดเดียวเพราะ GIL การเพิ่ม ประสิทธิภาพแบบเธรดเดียว จึงส่งผลโดยตรงต่อประสิทธิภาพที่ผู้ใช้ทั้งระบบนิเวศรับรู้ได้
ข้อเสนอ PEP 703 และความกังวลช่วงแรก
- Łukasz Langa เผยแพร่ฉบับแรกของ PEP 703 “Making the Global Interpreter Lock Optional in CPython” ซึ่ง Gross เป็นผู้เขียน ในเดือนมกราคม 2023
- นอกเหนือจากความคาดหวังต่อ no-GIL แล้ว โมดูลขยาย Python ที่เขียนด้วย C ก็กลายเป็นข้อกังวลหลัก
- GIL ทำหน้าที่ป้องกันปัญหาด้าน concurrency หลายอย่างในโค้ด C extension มาโดยตลอด
- การนำ GIL ออกอาจสร้างบั๊กแบบใหม่ในโค้ดเหล่านั้น
- มีฉันทามติว่าควรหลีกเลี่ยงการเปลี่ยนผ่านแบบ flag day เหมือนตอนย้ายจาก Python 2 ไป 3
- การเปลี่ยนผ่านสู่การนำ GIL ออกควรทำงานได้อย่างราบรื่นแม้กับโค้ดที่ยังไม่พร้อม
- Shannon ตั้งคำถามว่าความถดถอยของประสิทธิภาพในโค้ดเธรดเดียวระดับไหนจึงจะยอมรับได้ โดยประเมินเองว่าอยู่ในช่วง 15~20% และอาจสูงกว่านั้นได้ขึ้นกับผลกระทบต่อ PEP 659
- Eric Snow ในฐานะผู้เขียน PEP 684 “Per-Interpreter GIL” และ PEP 683 “Immortal Objects” ได้เขียนบทวิเคราะห์ยาว โดยมองว่าแนวทาง no-GIL กับแนวทาง subinterpreter ไม่จำเป็นต้องขัดแย้งกันเสมอไป
ต้นทุนและประโยชน์ที่เกิดกับ C extension
- Gross ตอบว่าผลกระทบต่อ C extension ไม่ได้มีแต่ด้านลบทั้งหมด
- ใน PEP มีการอ้างคำพูดของผู้ดูแล C API extension ที่ใช้งานแพร่หลาย เกี่ยวกับความซับซ้อนที่พวกเขาเผชิญในการหลบข้อจำกัดของ GIL
- Zachary DeVito ซึ่งเป็น PyTorch core developer ระบุว่าในช่วงไม่กี่เดือนที่ผ่านมา เขาใช้เวลาเพื่อทำความเข้าใจการ หลบข้อจำกัดของ GIL มากกว่าการแก้ปัญหาจริงอยู่หนึ่งหลัก
- no-GIL อาจสร้างปัญหา concurrency แบบใหม่ให้ผู้ดูแล extension module แต่ในเวลาเดียวกันก็อาจลดความซับซ้อนที่เกิดจากการต้องหลบ GIL ได้ด้วย
PEP ฉบับอัปเดตและข้อถกเถียงเรื่องประสิทธิภาพ
- ต้นเดือนพฤษภาคม 2023 Gross เผยแพร่ implementation ของ PEP 703 ที่อิงจาก Python 3.12 รุ่นพัฒนา พร้อม PEP ฉบับอัปเดต
- วันที่ 12 พฤษภาคม เขาขอให้ Steering Council ตัดสินใจเกี่ยวกับ PEP นี้ แต่ก่อนจะมีคำตัดสินก็ยังมีการถกเถียงเพิ่มเติมต่อเนื่อง
- วันที่ 2 มิถุนายน Shannon ประเมินผลกระทบด้านประสิทธิภาพของ PEP และเสนอช่วง 11~30% ซึ่งกลายเป็นประเด็นถกเถียง
- Shannon มองว่า interpreter แบบ adaptive specialization พึ่งพา GIL ดังนั้นหากยอมรับ no-GIL ก็จำเป็นต้องออกแบบกลยุทธ์ optimization ใหม่
- ความพยายามที่ใช้ไปกับการออกแบบใหม่และลงมือทำ จะไม่สามารถนำไปใช้กับงาน optimization จริงได้
- Langa เผยแพร่ตัวเลข benchmark ที่แสดงผลกระทบน้อยกว่าที่ Shannon ประเมินมาก และผลเพิ่มเติมก็ใกล้เคียงกับสิ่งที่ Gross รายงานไว้ใน PEP
บทเรียนจากการเปลี่ยนผ่าน Python 2→3
- Guido van Rossum มองว่าหากโค้ด Python 2 และ 3 สามารถอยู่ร่วมกันใน interpreter เดียวกันได้ ก็น่าจะช่วยให้การเปลี่ยนผ่านง่ายขึ้น
- เขาเน้นว่าหากจะเดินหน้า no-GIL โมดูลขยายที่ต้องการ GIL ก็ควร import ได้ใน no-GIL interpreter โดยไม่ต้องมีงานเพิ่ม
- โค้ดแอปพลิเคชันไม่ควรต้องแก้ไข
- โมดูลขยายก็ไม่ควรต้องแก้ไข
- Gregory P. Smith จาก Steering Council ระบุว่าขอบเขตผลกระทบของ PEP 703 ใหญ่มาก จึงยังไม่พร้อมตัดสินใจทันที
- Smith ยอมรับว่ามีความต้องการจริง แต่เห็นว่าต้องคำนึงถึงทั้งระบบนิเวศและหาวิธีเปลี่ยนผ่านที่ไม่ทำให้โลกพัง
- Gross ตอบโต้ว่า หากเลื่อนการตัดสินใจออกไปโดยไม่มีเกณฑ์การยอมรับและกำหนดเวลาที่ชัดเจน ในทางปฏิบัติมันก็ทำงานเหมือนคำว่า “no”
สามทางเลือกที่ทีม Faster CPython มองเห็น
- Shannon สรุปทางเลือกในอนาคตไว้สามแบบในการสนทนา “A fast, free threading Python”
- เดินหน้าตามแผนเดิมเพื่อสร้าง interpreter แบบเธรดเดียวที่เร็ว
- เดินหน้า interpreter แบบ free-threading no-GIL ที่มีผลกระทบต่อประสิทธิภาพเธรดเดียวซึ่งยังไม่แน่ชัด แต่ไม่ใช่ศูนย์
- เดินหน้าทั้งสองอย่างพร้อมกัน
- Shannon มองว่าต้องเลือกว่าจะจำกัดอะไรระหว่างประสิทธิภาพ ความขนาน และความเปลี่ยนแปลงได้ของข้อมูล
- เขาอธิบายว่ามันใกล้เคียงกับ “Performance, parallelism, mutability: pick one to restrict” มากกว่าจะเป็น “pick two”
- เขาเตือนว่าการทำให้ Python เร็วในสภาพแวดล้อม free-threading ต้องอาศัย งานวิจัยที่มีความคิดริเริ่มสูง และมีต้นทุนกับความเสี่ยงมากกว่า
- ตัวเลือกที่เขาชอบคือแบบที่สาม แต่ก็เห็นว่าไม่ควรเลือก no-GIL อย่างเดียวแล้วหวังว่า “เดี๋ยวใครสักคนจะแก้ปัญหาประสิทธิภาพให้เอง”
- van Rossum ก็เห็นว่าการได้ทั้ง free threading และ per-thread performance ที่เร็วเป็นทางเลือกที่ดีที่สุด แต่ย้ำว่าต้องใช้ทรัพยากรเพิ่มเติม
การสนับสนุนจากบริษัทและกระแสความเห็นของ core developer
- van Rossum ระบุว่า Microsoft จะยังสนับสนุนทีม Faster CPython ต่อไป และบทบาทของทีมนี้ไม่ได้จำกัดอยู่แค่งานด้านประสิทธิภาพเธรดเดียว
- เป้าหมายที่นำเสนอคือปรับงาน specialization และ optimization ให้เข้ากับโลก no-GIL เพื่อให้ในที่สุด no-GIL กลายเป็นโหมดบิลด์เดียวโดยไม่มีประสิทธิภาพเธรดเดียวถดถอย
- Carl Meyer จาก Meta ระบุว่าหาก PEP 703 ได้รับการยอมรับ Meta จะทุ่ม 3 engineer-years ภายในสิ้นปี 2025
- วิศวกรที่มีประสบการณ์กับภายในของ CPython จะร่วมงานกับทีม core dev
- ทำให้ implementation ของ PEP 703 เข้าไปอยู่ใน CPython ได้อย่างราบรื่น
- ปรับปรุงความเข้ากันได้และประสิทธิภาพของ no-GIL CPython อย่างต่อเนื่อง
- Stan Seibert จาก Anaconda ระบุว่าจะช่วยดูแลงานด้านแพ็กเกจจิงที่เกิดจากการนำ PEP 703 มาใช้
- รวมถึงงานที่เกี่ยวกับ pip, cibuildwheel และ conda-forge
- รวมถึงงานที่จำเป็นต่อการส่งมอบแพ็กเกจที่เข้ากันได้กับ no-GIL ให้ชุมชน Python
- ในแบบสำรวจ core developer มี 87% จาก 46 คนตอบว่าควรผลักดัน Python แบบ free-threaded อย่างจริงจัง และ 63% จาก 38 คนตอบว่ายินดีมีส่วนช่วยสนับสนุนและบำรุงรักษา no-GIL Python ตาม PEP 703
การตัดสินใจของ Steering Council และการเปลี่ยนผ่านแบบค่อยเป็นค่อยไป
- วันที่ 28 กรกฎาคม Thomas Wouters ประกาศว่า Steering Council ตัดสินใจรับ PEP 703 แต่รายละเอียดยังอยู่ระหว่างจัดทำ
- แนวทางคือเริ่มจากนำ no-GIL interpreter เข้ามาก่อนเพื่อดูว่าขาดอะไร แล้วค่อยเติมงานที่จำเป็นก่อนที่ no-GIL จะกลายเป็นค่าเริ่มต้น และในที่สุดเป็นเวอร์ชันเดียว
- คาดว่าช่วงเปลี่ยนผ่านจะใช้เวลาประมาณ 5 ปี
- Council ไม่ต้องการให้เกิดสถานการณ์แบบ Python 3 และมองว่าการแก้โค้ด third-party ที่จำเป็นเพื่อให้เข้ากับบิลด์ no-GIL ควรยังทำงานได้เหมือนเดิมบนบิลด์ with-GIL
- ในระยะสั้น มีการเสนอให้มีบิลด์ no-GIL เชิงทดลอง ซึ่งอาจเป็นช่วง Python 3.13
- Python 3.13 มีกำหนดในเดือนตุลาคม 2024
- เป็นบิลด์ให้ core developer และคนอื่น ๆ ใช้ทดลอง
- ในระยะกลาง no-GIL จะกลายเป็นตัวเลือกที่รองรับ แต่ยังไม่ใช่ค่าเริ่มต้น
- จังหวะเวลาจะขึ้นอยู่มากกับความเร็วที่ชุมชนยอมรับและสนับสนุนบิลด์ no-GIL
- ในระยะยาว no-GIL จะกลายเป็นบิลด์ค่าเริ่มต้น และ GIL จะถูกนำออกอย่างสมบูรณ์
- ต้องทำในรูปแบบที่ไม่ทำลาย backward compatibility โดยไม่จำเป็น
งานที่ยังไม่จบ
- Wouters มองว่าการนำ GIL ออกเป็นงานที่ใหญ่กว่าการรับ PEP หนึ่งฉบับมาก
- เหล่า core developer ต้องสั่งสมประสบการณ์กับ no-GIL Python แล้วใช้สิ่งนั้นนำทางชุมชนที่เหลือ
- ในกระบวนการจัดระเบียบ thread safety ของโค้ดเดิม อาจจำเป็นต้องมี C API และ Python API ใหม่
- ตลอดทั้งกระบวนการ ต้องมีการประเมินความคืบหน้าและกำหนดเวลาใหม่เป็นระยะ
- ต้องไม่ปล่อยให้กลายเป็นสงคราม backward compatibility ยาวอีก 10 ปี
- หากเห็นว่า PEP 703 กำลังกลายเป็นปัญหา ก็ควรหยุดและมองหาทางออกอื่นได้
- กว่าจะไปถึง Python แบบ no-GIL-only ยังเหลืองานวิจัย การเขียนโค้ด การทดสอบ การทดลอง และการทำเอกสารอีกมาก โดยมีการยกตัวอย่างว่าอาจเป็น Python 3.17 ในเดือนตุลาคม 2028
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
บทความเขียนได้ดีและสรุปกระบวนการทั้งหมดได้ดี แต่ค่อนข้างให้น้ำหนักกับฝ่าย คัดค้านการถอด GIL และความเป็นไปได้ที่จะล้มเหลวมากกว่า
ฝ่ายตรงข้ามก็ควรถูกเน้นให้เพียงพอเช่นกัน คุณภาพงานของ Sam Gross สูงมาก และเขายังใส่การปรับปรุงประสิทธิภาพที่ไม่ได้เกี่ยวข้องโดยตรงกับ no-GIL เพื่อลดการสูญเสียประสิทธิภาพด้วย แนวทางโอเพนซอร์สก็เดินหน้าได้ดีมาก และแม้การตอบสนองจะช้ามากจนหากไม่มีแรงกดดันจากชุมชน คณะกรรมการกำกับดูแลก็คงปล่อยค้างไว้นานต่อไป เขาก็ยังแสดงความอดทน ซับอินเทอร์พรีเตอร์แทบยังไม่เคยแสดงประโยชน์ใช้สอยใน Python โดยเฉพาะตัวชี้วัดจริงจัง และครั้งนี้ใกล้เคียงกับความพยายามครั้งแรกที่นิยามชัดเจนและวัดผลได้ ปฏิกิริยาจากชุมชนก็แสดงความสนใจอย่างมากต่อโปรเจกต์นี้ และคณะกรรมการกำกับดูแลก็สรุปว่า “มีเจตนาจะรับ PEP 703 และกำลังปรับเงื่อนไขรายละเอียดสำหรับการยอมรับ” ผมไม่ใช่แฟนตัวยงของ no-GIL และถ้าสุดท้ายไม่ถอดออกก็ไม่เป็นไร อีกทั้งมองว่าควรลองซับอินเทอร์พรีเตอร์ก่อน แต่ก็ควรมองอย่างยุติธรรม
ผลลัพธ์ก็น่าประทับใจทีเดียว: https://lwn.net/SubscriberLink/941090/8bcb029dbf548f26/ ดูเหมือนจะออกมาดีเท่าที่คาดหวังได้ งานซับอินเทอร์พรีเตอร์น่าจะเดินคู่ขนานกับงาน free-threading และทั้งสองมีกรณีใช้งานต่างกัน
เท่าที่ทราบ PDM ยังรองรับอยู่ ผมไม่ชอบที่ต้องใช้ virtualenv สำหรับการ build และ deploy และอยากให้ Python ทำงานได้เหมือน JavaScript มีการพิสูจน์แล้วว่าทำได้ เธรดอภิปรายอยู่ที่ https://discuss.python.org/t/pep-582-python-local-packages-d... การเอาคำว่า “มีวิธีที่ถูกต้องเพียงวิธีเดียวเท่านั้น” มาใช้เหมือนเป็นเหตุผลในการปฏิเสธก็น่าหงุดหงิด เพราะไม่เคยรู้สึกว่าคำนั้นเป็นจริงใน Python เลย
เป็นบทความยอดเยี่ยมของ LWN และคุ้มค่าแก่การอ่านมาก ตอน NoGIL ของ Sam Gross ถูกนำเสนอครั้งแรก ผมก็คาดหวังไว้ แต่หลังอ่านบทความและย้อนดูประสบการณ์ส่วนตัว ความคิดก็เริ่มเปลี่ยน
ผมเคยสร้างระบบแบ็กเอนด์ด้วยหลายภาษา และโดยรวมมีอยู่แค่สองประเภท ประเภทหนึ่งคือระบบที่เปิด network endpoint รับ request แล้วคำนวณและส่ง network request อื่นก่อนตอบกลับ อีกประเภทคือระบบที่อ่านข้อความจากคิวหรือฐานข้อมูล หรือ polling API อื่น ๆ แล้วคำนวณและเรียก network ก่อนส่งไปยังคิวอื่น ประเภทแรกให้ความสำคัญกับ latency ส่วนประเภทที่สองให้ความสำคัญกับ throughput ในประเภทแรก NoGIL มีประโยชน์ เพราะอยากสร้าง thread ตาม request ไม่ให้ endpoint ที่คำนวณหนักไปบล็อก request อื่น และอยากแชร์ database connection pool ส่วนประเภทที่สอง แม้ในภาษาที่ไม่มี GIL ผมแทบจำไม่ได้ว่าเคยใช้ parallelism หรือ concurrency ภายในโปรเซสที่มีทรัพยากรร่วมกัน และมันจะเข้าใจยากเกินไป การปรับแต่งมักเป็นการ batch processing อย่างชาญฉลาด และ parallelism ก็คือการรันโปรเซสอิสระหลายตัวบนหลายเครื่อง ถ้า NoGIL ทำให้คุณภาพของระบบประเภทที่สองต้องประนีประนอม ก็คงน่าผิดหวังมาก และจริง ๆ ตอนนี้พลังงานทางความคิดส่วนใหญ่ของผมก็ใช้ไปกับการปรับปรุงประเภทที่สองอยู่
ตอนนี้ผมใช้ QThread ทำ JournalParser โดย parser นี้จะอ่าน event ของเกมอย่างต่อเนื่องจากไฟล์ player journal ที่ Elite: Dangerous และ Odyssey สร้างขึ้น แล้วปล่อย QSignal แบบกำหนดเองตามแต่ละ event เพื่อให้ slot ที่ฟัง Signal นั้นจัดการ ส่วนอื่น ๆ ของแอปพลิเคชันก็น่าจะได้ประโยชน์ไม่น้อยถ้าไม่มี GIL https://captainslog.scarygliders.net/captains-log-2/
แล้วโค้ดของทุกคนก็อาจดีขึ้นได้
แน่นอนว่าอาจบอกได้ว่าไม่ควรเขียนโปรแกรมที่เน้น CPU ด้วย Python ตั้งแต่แรก แต่นั่นก็เป็นอีกเรื่องหนึ่ง
ถ้าทรัพยากรร่วมนั้นเป็นแบบอ่านอย่างเดียว ก็ไม่ค่อยเข้าใจว่ามันจะสับสนตรงไหน
ผมสงสัยว่าประโยคในเธรดที่ลิงก์ไว้ว่า “การนำ GIL ออกมีโอกาสน้อยมากที่จะทำให้ codebase ที่เขียนด้วย Python ล้วน ๆ พัง” นั้นจริงหรือไม่
โค้ด Python แบบ multithread บางส่วนอาจคาดหวังว่า operation บางอย่างจะ thread-safe โดยปริยายเพราะมี GIL ตัวอย่างเช่น การที่สอง thread เพิ่ม item ลงใน list เดียวกันแล้ว list ไม่เสียหาย เป็นเพราะ GIL ทำให้สอง thread ไม่ได้รัน operation นั้นแบบขนานกัน หากนำ GIL ออก โค้ดแบบนี้อาจถูกลงโทษขึ้นมาทันที คล้ายกับตอนแก้ไข
std::vectorพร้อมกันใน C++ ผมไม่มั่นใจ แต่ประโยคนี้ดูน่าสงสัยอยู่บ้าง https://discuss.python.org/t/pep-703-making-the-global-inter...ส่วน container thread safety ของ PEP 703 พูดถึงปัญหานี้ โดยเสนอให้ list, dictionary, set แต่ละตัวมี lock เบา ๆ แยกตาม object และ operation ทั้งหมดที่แก้ไข object ต้องจับ lock นั้น รวมถึง operation อ่านส่วนใหญ่ก็ควรจับ lock ด้วย รายละเอียดอยู่ที่ https://peps.python.org/pep-0703/#container-thread-safety
แต่ถ้าทำแบบนั้นก็ยังเหลือคำถามว่า เมื่อจำเป็นต้องใช้
[]ที่ไม่ synchronized จะทำอย่างไรยากจะนึกถึงบททดสอบของ open source ที่ยากกว่านี้
ตัวการตัดสินใจเองก็สมเหตุสมผล คือเดินหน้าด้วยโหมดทดสอบ มอง multi-interpreter เป็นการทดลองขั้นกลาง แต่ตั้งเป้าไว้ที่ Python ที่รันพร้อมกันได้ อย่างไรก็ตาม ข้อจำกัดที่ต้องรันโค้ดเดิมและโค้ดใหม่บน virtual machine เดียวกันนั้นใหญ่มาก น่าแปลกที่สรุปของ LWN แทบไม่ได้พูดถึงการทดสอบ ทั้งที่การทดสอบยังมีหลายอย่างที่ยังไม่คลี่คลาย และอาจนำไปสู่ release ที่มี bug ร้ายแรงซึ่งยังไม่รู้จักได้ Microsoft, Facebook/Meta, Conda ลงทรัพยากรให้ และผู้มีส่วนร่วมหลักส่วนใหญ่ท่วมท้นอยากเดินหน้า แต่ถ้างานยากขึ้นและต้องการคนมากขึ้น จะเป็นอย่างไรก็ยังไม่ชัดเจน ขณะเดียวกัน โปรเจกต์มหาศาลในแวดวงวิชาการและอุตสาหกรรม ตั้งแต่เว็บไซต์ไปจนถึง big data และ AI ต่างพึ่งพา Python และต้นทุนที่จะถูกผลักไปให้ Python developer อาจวัดได้เป็นสัดส่วนของ GDP ด้วยซ้ำ ดูเหมือนว่ายังไม่ได้รู้ปัญหาต่าง ๆ ทั้งหมดด้วยซ้ำ ดังนั้นควรโฟกัสกับแนวทาง Faster CPython ที่ปรับปรุงอย่างคาดการณ์ได้ไปอีก 3 ปีขึ้นไป และผู้สนับสนุน Python แบบรันพร้อมกันควรวิเคราะห์ให้เกินกว่า prototype ง่าย ๆ ว่าอาจเกิดปัญหาอะไร จะตรวจจับอย่างไร และทำอะไรได้บ้าง ควรให้คนที่มีพื้นฐานด้านการพิสูจน์การรับประกัน concurrency มาตรวจทาน และเมื่ออย่างน้อยระบุสิ่งที่ยังไม่รู้ได้แล้วค่อยส่งคำถามไปยัง steering committee จึงจะยุติธรรมกว่า open source ไม่ค่อยมีการตัดสินใจในระดับ program management มากนัก และมักมีการตัดสินใจที่ค่อนข้างง่ายซึ่งขับทิศทางตลาด เช่น Apache, Eclipse, Linux แต่ครั้งนี้มีสิ่งที่ยังไม่รู้ทางเทคนิคจริง ๆ ขณะเดียวกันก็รู้สึกว่าควรจัดการ ABI ข้ามภาษา ด้วย ปัญหาใหญ่คือการทำให้เข้ากับ execution model ที่ C คาดหวังไว้ ส่วน foreign function และ memory interface ของ Java ก็ยังอยู่ใน incubation มาหลายปีแล้ว และ Swift ก็ wrapping C กับ C++ ได้ดีขึ้น แต่ FFI ขึ้นชื่อว่ายาก และอาจยากโดยไม่จำเป็นด้วย
โดยส่วนตัวคิดว่า การนำ GIL ออกเป็นความผิดพลาด แอปพลิเคชันที่จะได้ประโยชน์แรง ๆ มีไม่มาก และส่วนใหญ่จะเจอ performance penalty
งานนี้จะกินความสนใจและความพยายามไปหลายปี ซึ่งน่าจะเอาไปใช้ให้ฉลาดกว่านี้ได้ Python ดูเหมือนมีความกังวลหรือปมด้อยเกี่ยวกับ GIL ผมว่าควรยอมรับโมเดล single-thread อย่างเต็มที่เหมือน JavaScript ไปเลยดีกว่า บางแอปพลิเคชันอาจยังยากหรือเป็นไปไม่ได้ต่อไป แต่ผมคิดว่า Python ไม่ใช่ตัวเลือกที่ดีสำหรับแอปที่ต้องการ performance สูงหรือ scalability สูง การมีความเฉพาะทางระดับหนึ่งและไม่รองรับทุก use case ไม่จำเป็นต้องเป็นเรื่องแย่
ผู้คนต้องการ performance สำหรับสิ่งที่ตอนนี้พวกเขาทำด้วย Python อยู่แล้ว เราไม่สามารถย้อนกลับไปยังยุคที่เรื่องนี้ไม่จริงได้ ตอนนี้มันเป็นหนึ่งใน use case ที่พบบ่อยที่สุดของ Python และผู้คนเอาอาชีพไปผูกกับมันอยู่
ผู้คนพยายามทำงานแบบ parallel ด้วย Python อยู่แล้ว การบังคับให้ใช้ภาษาอื่นไม่ได้ช่วยมากนัก
งาน data-intensive จำนวนไม่น้อยสามารถรันเป็น process แบบ parallel จาก Python ได้ง่าย ๆ อยู่แล้ว จึงไม่แน่ใจว่าการนำ GIL ออกจะให้ประโยชน์ใหญ่ขนาดนั้นหรือไม่
ประสิทธิภาพแบบเธรดเดียวควรได้รับความสำคัญกว่า เพราะยากกว่ามากที่จะปรับปรุงด้วยการทุ่มเงินเพิ่ม
ประสิทธิภาพแบบหลายเธรดสามารถเพิ่มคอร์อีกหนึ่งคอร์เพื่อชดเชย overhead ของการทำ parallelization แบบอิงโปรเซสได้ มองว่าการแบ่งเป็นสองขั้วว่า GIL กับ no-GIL นั้นผิดตั้งแต่ต้น ปัญหาใหญ่ที่สุดของ multiprocessing คือไม่สามารถแชร์หน่วยความจำได้ ดังนั้นก็แค่เพิ่ม virtual process ที่มีกลไกแชร์หน่วยความจำอย่างชัดเจนเข้าไป แบบนั้นอ็อบเจ็กต์จะอยู่ในเธรดเดียว จึงยังรักษาการ optimize แบบเธรดเดียว เช่น reference counting ที่ไม่มี barrier ได้
แม้ไม่มี GIL ก็ทำให้ประสิทธิภาพแบบเธรดเดียวดีก็ได้ Rust มีแนวคิดเรื่อง abstraction ที่ไม่มีต้นทุน และจัดการ thread ได้ดี Java ก็ทำงานแบบเธรดเดียวได้ดี ยังมีภาษาอื่นอีกมาก และนี่ไม่ใช่นิยายวิทยาศาสตร์ lock สามารถหายไปได้ด้วย optimization, หรืออาจเลือกเขียนโค้ดแบบ lock-free ตั้งแต่แรกก็ได้ รวมถึงทำ concurrency แบบละเอียดหรือแบบมีโครงสร้างก็ได้ด้วย อะไรที่ thread-safe นั้นโดยพื้นฐานแล้วเป็นสัญญาของ API optimistic locking ก็มีอยู่ ไม่มีเหตุผลดี ๆ ที่ Python จะทำสิ่งคล้ายกันไม่ได้ แต่ต้องเอา GIL ออกก่อน ประสิทธิภาพที่ลดลงของ Python แบบไม่มี GIL ส่วนใหญ่ใกล้เคียงกับ technical debt ที่ยังไม่ได้สะสาง และแก้ได้เมื่อเวลาผ่านไป การใส่ lock จำนวนมากเป็นเพียงวิธีแก้เฉพาะหน้า จึงทำให้ช้าลง แต่ทางออกที่ถูกต้องน่าจะเป็นการคิดการทำงานภายในใหม่ หรือมีสัญญา API ที่ระบุว่าอะไร thread-safe บ้าง runtime และ compiler ของ Python ที่เร็วขึ้นอาจทำให้สิ่งจำนวนมากที่ตอนนี้พึ่งพา native library สามารถนำกลับมา implement ด้วย Python ได้ด้วย การโต้ตอบกับ native code ต่างหากที่เป็นจุดที่มักต้องใช้ lock และถ้าไม่เปลี่ยนวิธีนั้นก็จะยังเป็นปัญหาต่อไป แก่นของการเอา GIL ออกคือการค้นหาและแก้สิ่งเหล่านี้อย่างเป็นระบบ และมันจะดีขึ้นเมื่อเวลาผ่านไป
ปัญหาเดียวของ Python/multiprocessing คือบางครั้งสิ่งที่ต้องการไม่ใช่ queue แต่เป็น shared mutable state วิธีวางอ็อบเจ็กต์ Python ไว้ใน shared memory ตอนนี้ซับซ้อน จำกัด และไม่มีประสิทธิภาพ สิ่งที่ควรแก้คือส่วนนั้น และ Python จำเป็นต้องรองรับการวาง native instance ไว้ใน shared memory ให้ดีกว่านี้
สำหรับคำถามว่า “ประสิทธิภาพของโค้ดเธรดเดียวลดลงได้มากแค่ไหนจึงจะยอมรับได้” Shannon ประเมินไว้ราว 15~20% แต่โดยรวมแล้วคำถามนั้นแทบไม่ได้รับคำตอบ
แปลว่าคนบางส่วนในโปรเจกต์ที่กำลังทำให้ “CPython เร็วขึ้น” มองว่ายอมรับได้ที่จะทำให้โค้ด Python เดิมส่วนใหญ่ช้าลง 15~20% ในชั่วข้ามคืนอย่างนั้นหรือ? คิดว่าขีดจำกัดควรอยู่ราว 5% เป็นอย่างมาก และแม้แต่เท่านั้นก็ยอมรับได้ก็ต่อเมื่อการเอา GIL ออกช่วยให้ optimization อื่น ๆ ในอนาคตดีขึ้นเท่านั้น แต่กลับมีคนบอกว่าการเปลี่ยนแปลงนี้ทำให้ optimization อื่นซับซ้อนและล่าช้าขึ้นเสียอีก อีกด้านหนึ่ง Shannon เคยเสนอระดมทุนส่วนตัวในปี 2020 เพื่อทำให้ CPython เร็วขึ้น 5 เท่า และตอนนี้มีทั้งทีมที่ได้รับการสนับสนุนจากบริษัทใหญ่กว่ามากกำลังทำให้ CPython เร็วขึ้น แต่เป้าหมายดูเล็กลงมาก
เมื่อประสิทธิภาพสำคัญจริง ๆ ถ้าได้ความเร็วเพิ่มขึ้นราว 20 เท่าโดยไม่ต้องเขียนใหม่ด้วยภาษาอื่น ก็มีความหมายมาก
ถ้า optimization อื่นไม่ได้หยุดลง แต่แค่ใช้เวลานานขึ้นเล็กน้อย ก็อาจยอมรับได้
ถ้าเทียบโค้ดจริงที่มีการคำนวณตัวเลขและสตริงโดยไม่มีการเข้าถึงเครือข่ายหรือดิสก์ 3.12 beta ใช้เวลาน้อยกว่า 3.8 เพียงประมาณ 20~25% เท่านั้น นั่นคือระดับเดียวกับ 2.7 ดูเหมือนบุคคลแกนหลักรุ่นเก่ากำลังสิ้นหวังในการหา feature แบบ bullet point เพื่อโชว์ผู้สนับสนุนองค์กรในรีลีสถัดไป จึงเอางานของ Sam Gross มาใช้ แต่เมื่อเวลาผ่านไป คงค่อย ๆ รับเครดิตไปเอง
เป็นบทสรุปที่ยอดเยี่ยมสมกับ LWN
ชอบชุมชน Python เป็นตัวอย่างชั้นนำของซอฟต์แวร์โอเพนซอร์ส และแสดงให้เห็นว่า ความโปร่งใสกับธรรมาภิบาลที่ดี สามารถบรรลุอะไรได้บ้าง เวลาวิศวกรรมที่ Meta, Microsoft และรายอื่น ๆ投入เข้ามานั้นน่าขอบคุณ แต่เมื่อเทียบกับคุณค่าที่อุตสาหกรรมเทคโนโลยีทั้งหมดและวงกว้างกว่านั้นรวมถึง data science ได้รับจาก Python และซอฟต์แวร์โอเพนซอร์สแล้ว ก็ยังน้อยเกินไปมาก
เมื่อ 8 ปีก่อนที่ JPMorgan เคยโน้มน้าวทีมผู้นำด้านเทคโนโลยีให้สนับสนุน PyCon UK, ตั้งบูธรับสมัครงาน และสนับสนุนให้นักพัฒนารุ่น junior ของ JPMorgan จากทั่วสหราชอาณาจักรเข้าร่วม แม้ออกจาก JPM มา 5 ปีแล้ว แต่บริษัทยังเป็น headline sponsor ของ PyCon UK อยู่ ค่าใช้จ่ายนั้นแทบจะละเลยได้เมื่อเทียบกับผลประโยชน์มหาศาลที่ได้รับจาก Python และระบบนิเวศโอเพนซอร์ส
mailing list ถูกเซ็นเซอร์ และวงในไม่สามารถถูกวิจารณ์ได้ ผู้มีส่วนร่วมตัวจริงถูกเอาเปรียบโดยคนที่อยู่ในบริษัทที่ถูกต้องและแทบไม่ได้ทำอะไร แต่ครองตำแหน่งอำนาจเชิงธุรการไว้ บทความของ LWN นั้นเป็นมิตรมากและมักเอ่ยชื่อผู้มีอำนาจตัดสินใจอยู่เสมอ จึงไม่ควรถูกหลอก มองว่าใกล้เคียงกับการรายงานแบบเลือกข้าง
วิธีที่ Sam Gross ผลักดันเรื่องนี้ค่อนข้างน่าประทับใจ หลังได้รับปฏิกิริยาเชิงบวกแต่ไม่มีคำตอบแน่ชัดจากคณะกรรมการกำกับ เขาอาจแค่นั่งรอความคืบหน้าก็ได้ แต่การที่เขา คัดค้านและกดดัน นั้นเป็นเรื่องที่ควรชื่นชมอย่างมาก
น่าสนใจมาก การที่ Sam Gross กล่าวว่า “ตอนนี้ยังไม่จำเป็นต้องได้คำตอบ yes/no ทันที แต่เราจำเป็นต้องรู้ว่าการยอมรับจะมีหน้าตาเป็นอย่างไร และประเด็นนี้ถูกปล่อยทิ้งไว้นานเกินไปแล้ว” ถือเป็นการเคลื่อนไหวที่กล้าหาญมาก: https://github.com/python/steering-council/issues/188#issuec...
ปฏิสัมพันธ์นั้นอาจไหลไปได้หลายทิศทาง แต่ดูเหมือนจะเป็นแรงกระตุ้นที่คณะกรรมการกำกับดูแลต้องการพอดี เส้นทางสู่ no-GIL Python ยังยาวและคดเคี้ยว และคงต้องใช้แรงงานระดับหลายสิบ engineer-year แต่ดูเหมือนว่าอย่างน้อยก็มีเส้นทางที่เป็นรูปเป็นร่างแล้ว ส่วนที่ยากที่สุดคือการรับประกันความถูกต้องของ codebase เดิม การพูดว่าไม่อยากให้ซ้ำรอยช่วงเปลี่ยนผ่านจาก Python 2 ไป 3 กับการที่ผู้คนหลีกเลี่ยงการอัปเกรดจริง ๆ เพราะกลัวบั๊ก แม้จะยืนยันว่าไม่มี breaking changes นั้นเป็นคนละเรื่องกันโดยสิ้นเชิง ต่อให้วาง GIL/no-GIL ไว้เป็นเพียงสวิตช์ตอน compile time ค่าใช้จ่ายในการดูแลรักษาก็จะเพิ่มขึ้นแน่นอน ถึงอย่างนั้นในระยะยาวผมคิดว่าความพยายามนี้คุ้มค่า GIL เป็นเหมือนสายล่อฟ้าของคำวิจารณ์ต่อ Python และแค่ดูเธรด HN เกี่ยวกับ Python กับ parallelism ก็พอจะเห็นได้ อาจเป็นเพราะมันเป็นสิ่งที่ผู้คนสามารถชี้ตรง ๆ แล้วพูดว่า “นี่คือเหตุผลที่ Python เร็วกว่านี้ไม่ได้” โดยไม่ต้องเข้าใจบริบทหลายสิบปี ในแง่นั้นมันใกล้เคียงกับ บอสตัวสุดท้ายของรั้วของ Chesterton
แม้ภายใต้แนวทางใหม่ ความพยายามหลายปีเพื่อเอา GIL ออกก็ยังมีความเป็นไปได้ที่จะถูกปฏิเสธในท้ายที่สุด