1 คะแนน โดย GN⁺ 2023-10-22 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • Python steering council แสดงเจตนาจะอนุมัติ PEP 703 เพื่อทำให้ GIL เป็นตัวเลือก ตลอดหลายรีลีส โดยเงื่อนไขสุดท้ายยังอยู่ระหว่างการปรับให้ลงตัว
  • บิลด์ --disable-gil ของ CPython 3.13 จะถูกเตรียมไว้ในฐานะฟีเจอร์ทดลอง และประเด็นทางเทคนิคที่ใหญ่ที่สุดตอนนี้คือ stable ABI กับความเข้ากันได้ของ wheel สำหรับโมดูลเสริม
  • เนื่องจาก wheel abi3 เดิมอาจไม่สามารถใช้กับ no-GIL CPython 3.13 ได้ตรง ๆ จึงมีการหารือเรื่องการเพิ่ม abi4, การเปลี่ยนแปลง limited C API และการแปลงแมโครอ้างอิงการนับ refcount ให้เป็นการเรียกฟังก์ชัน
  • มีความกังวลว่า pip อาจเลือก wheel สำหรับบิลด์ GIL และ no-GIL ผิด และการติดตั้งผิดแบบเงียบ ๆ นั้นอันตรายกว่าการติดตั้งล้มเหลวแบบชัดเจน
  • มีการเสนอให้ใช้ชื่อบิลด์ no-GIL ว่า free-threading แทน nogil แต่ยังต้องแก้ปัญหาเรื่องชื่อไฟล์รัน, shebang, การติดตั้งคู่ขนาน และการแพ็กเกจในดิสทริบิวชันไปพร้อมกัน

ตำแหน่งปัจจุบันของ PEP 703 และ no-GIL CPython

  • Python steering council แสดงเจตนาจะอนุมัติ PEP 703 เมื่อปลายเดือนกรกฎาคม โดย PEP นี้มีเนื้อหาเกี่ยวกับการทำให้ global interpreter lock (GIL) เป็นตัวเลือกใน CPython
  • แม้เงื่อนไขรายละเอียดของการอนุมัติยังไม่ถูกสรุป окончательно แต่การอภิปรายด้านการใช้งานจริงและการเตรียมระบบนิเวศได้เริ่มเดินหน้าแล้ว
  • ในระยะยาวมีภาพเส้นทางไปสู่ CPython เวอร์ชันเดียวที่ไม่มี GIL แต่ในระยะสั้นยังเป็นช่วงทดลองพฤติกรรม no-GIL บนอินเทอร์พรีเตอร์ที่บิลด์ด้วยตัวเลือก --disable-gil
  • CPython 3.13 มีกำหนดในเดือนตุลาคม 2024 และบิลด์ no-GIL ของเวอร์ชันนี้จะมีสถานะเชิงทดลอง

stable ABI และความเข้ากันได้ของโมดูลเสริม

  • Sam Gross พูดถึงวิธีที่ PEP 703 จะทำงานร่วมกับ stable ABI ของ CPython บน Python discussion forum
  • stable ABI มีไว้เพื่อให้โมดูลเสริมทำงานข้ามหลายเวอร์ชันของ CPython ได้ด้วย binary wheel เดียว โดยไม่ต้องรีบิลด์ใหม่ทุกครั้งที่มีรีลีส CPython ใหม่
  • ส่วนขยายที่บิลด์สำหรับ stable ABI อาจไม่สามารถทำงานได้ตรง ๆ บนบิลด์ no-GIL ของ CPython 3.13
  • เพื่อแก้ปัญหานี้ จึงมีข้อเสนอให้เพิ่มและปรับบางส่วนของ limited C API
    • ส่วนขยายที่ใช้เฉพาะ limited C API จะสามารถสร้างไบนารีที่ใช้ stable ABI ได้
    • ข้อเสนอการเปลี่ยนแปลงรวมถึงแผนเดิมในการเปลี่ยนแมโครบ้างตัวที่เพิ่มหรือลด reference count ของอ็อบเจ็กต์ให้เป็น การเรียกฟังก์ชัน
  • เป้าหมายคือทำให้เกิดไบนารีส่วนขยายที่ใช้งานได้ทั้งบนบิลด์ GIL และ no-GIL

abi3, abi4 และปัญหาการเลือก wheel

  • Victor Stinner มองว่าหากการทดลอง no-GIL จะประสบความสำเร็จ จำเป็นต้องมีทางออกที่เรียบง่ายสำหรับส่วนขยายที่ทำงานได้กับอินเทอร์พรีเตอร์ทั้งสองแบบ
  • เนื่องจากส่วนขยายที่บิลด์สำหรับ stable ABI บน CPython 3.12 หรือต่ำกว่า จะไม่เข้ากันกับบิลด์ no-GIL หลัง 3.13 จึงมีข้อเสนอให้สร้าง ABI เวอร์ชันใหม่ชื่อ abi4
    • stable ABI ปัจจุบันคือ abi3
    • หมายเลข ABI ไม่จำเป็นต้องผูกกับหมายเลขเมเจอร์เวอร์ชันของ CPython เสมอไป
  • Gross มองว่าส่วนขยายที่ต้องการรองรับ no-GIL น่าจะรับภาระการสร้าง binary wheel สองชุดได้ในระดับหนึ่ง
    • เขากังวลมากกว่าว่าโครงการ no-GIL จะถูกผูกติดกับการปรับปรุง C API และ stable ABI มากเกินไป
  • Alex Gaynor ซึ่งมีแพ็กเกจ abi3 wheel หลายตัว ก็มองว่าการต้องสร้างสอง wheel เพียงครั้งเดียวไม่ใช่ภาระที่หนักเกินไป
    • แต่ประเด็นสำคัญคือ pip ทั้งปัจจุบันและในอนาคตจะเลือก wheel ที่ถูกต้องจากสองตัวนี้ได้หรือไม่
  • Brett Cannon มองว่าลอจิกปัจจุบันของ pip ยังแยกสองเวอร์ชันนี้ไม่ได้ ดังนั้นหากไม่มีการเปลี่ยนแปลงอย่าง abi4 ทั้ง pip รุ่นเดิมและรุ่นเก่าจะไม่สามารถทำงานได้ถูกต้อง

ความกังวลเรื่อง pip ทำงานผิดแบบเงียบ ๆ

  • Gross มองว่าในบิลด์ทดลอง --disable-gil ของ CPython 3.13 ไม่จำเป็นต้องกังวลเรื่องการรองรับ pip รุ่นเก่ามากนัก
    • เพราะ pip รุ่นเก่าที่พังบน Python เวอร์ชันใหม่เป็นเรื่องที่เกิดขึ้นบ่อย
    • เขายกตัวอย่างกรณี pip==23.1.1 หรือต่ำกว่าที่พังบน CPython 3.13 เพราะไม่มี pkgutil.ImpImporter
  • Paul Moore ผู้ดูแล pip มองว่า การพังแบบชัดเจน กับ การติดตั้งแพ็กเกจผิดแบบเงียบ ๆ เป็นคนละปัญหา
    • ยังมีผู้ใช้ที่ใช้ pip รุ่นเก่า
    • ผลกระทบต่อผู้ใช้ต่างกันระหว่างความล้มเหลวที่ชัดเจนกับข้อผิดพลาดแบบเงียบ
  • Moore กังวลว่าหากผู้ใช้ที่อยากทดลองบิลด์ no-GIL หรือ free-threaded ต้องมานั่งดีบักปัญหาความเข้ากันได้ของ ABI อาจทำให้หมดแรงจูงใจ
  • Gaynor ก็เห็นว่าถ้า pip ทำงานผิดแบบเงียบ ๆ กับแพ็กเกจที่ได้รับผลกระทบ อาจมี issue หลั่งไหลเข้ามาจำนวนมาก

การติดตั้งแบบคู่ขนานและชื่อไฟล์รัน

  • Barry Warsaw ถามว่ามีแผนจะติดตั้งบิลด์ GIL และ no-GIL ไว้ร่วมกันในระบบเดียวหรือไม่
  • Gross ตอบว่าสถานการณ์นี้คล้ายกับการติดตั้ง Python คนละเวอร์ชัน
  • Cannon มองว่าการใส่ไบนารีสองตัวไว้ใน “fat” wheel เดียวก็เป็นไปได้
    • เพียงแต่ชื่อไบนารีภายใน wheel ต้องต่างกัน
  • การถกเรื่องชื่อไฟล์รันจึงต่อยอดไปเป็นอีกเธรดหนึ่ง
  • Paul Moore มองว่าผู้ใช้ควรสามารถทดสอบโหมด no-GIL ได้ง่าย และเลือกใช้ GIL/no-GIL ได้สะดวก
    • หากกระบวนการนี้ยากบน Windows, macOS, Linux ฯลฯ ก็อาจส่งผลลบต่อโครงการ no-GIL
    • ผู้ใช้ต้องลองได้ง่าย จึงจะเกิดความต้องการบิลด์ no-GIL และเกิดแรงกดดันต่อผู้ดูแลแพ็กเกจให้จัดทำ wheel ที่เข้ากันได้กับ no-GIL

ข้อถกเถียงเรื่องชื่อ nogil กับ free-threading

  • Barry Scott มองว่าชื่อไฟล์รันสำคัญ เพราะต้องใช้ระบุว่าจะเรียกอินเทอร์พรีเตอร์ตัวใดในบรรทัด shebang
    • เขายกตัวอย่างชื่ออย่าง python-nogil3, python-nogil3.13
  • Gregory P. Smith แสดงความเห็นส่วนตัวว่าบิลด์ no-GIL ของ CPython 3.13 เป็นฟีเจอร์ทดลอง ดังนั้นดิสทริบิวชันไม่ควรนำไปไว้ใน $PATH เริ่มต้น
    • เขายังมองว่าไม่ควรให้ชื่อไฟล์รันที่ยาวค้างอยู่ใน shebang ไปอีกนาน
    • จึงเสนอให้เลื่อนการตัดสินใจเรื่องชื่อสำหรับการติดตั้งออกไปหลัง 3.14
  • Petr Viktorin นักพัฒนา Fedora ชี้ว่าดิสทริบิวชันมีแนวโน้มสูงที่จะทำแพ็กเกจอินเทอร์พรีเตอร์ no-GIL ให้ผู้ใช้ทดลอง
  • Moore มองว่าอยากระบุบิลด์ free-threaded ด้วยรูปแบบอย่าง #!/usr/bin/env python3.13-nogil
    • เพื่อหลีกเลี่ยงการฮาร์ดโค้ดพาธที่ยาวและไม่เป็นธรรมชาติ
  • ในเธรดเกี่ยวกับตัวติดตั้งบน Windows ที่ Steve Dower เป็นผู้เริ่ม Smith ระบุว่า steering council ต้องการหลีกเลี่ยงชื่อ nogil
    • เหตุผลคือคำนี้สื่อสารกับนักพัฒนาที่ไม่ใช่ core developer ได้ไม่ดี คนส่วนใหญ่ไม่จำเป็นต้องรู้ว่า GIL คืออะไร และยังเป็นการตั้งชื่อเชิงปฏิเสธ
    • ทางเลือกที่ถูกเสนอคือคำว่า free-threading
  • Gross มองว่า free-threading เองก็ไม่ใช่คำที่คนภายนอกเข้าใจง่ายหรือเป็นคำที่ใช้กันแพร่หลาย
  • ในการอภิปรายจริงมีแรงสนับสนุนต่อชื่อที่สั้นมาก และ nogil ก็เป็นตัวเลือกที่เด่นที่สุดในแง่นั้น
  • การเปลี่ยนแปลงที่สะท้อนออกมาอย่างเป็นรูปธรรมคือการเปลี่ยน ABI tag ของบิลด์ no-GIL จาก n เป็น t
    • t หมายถึง threading

ข้อเสนอ abi4 และงานที่ยังเหลือ

  • Gross และ Viktorin พูดคุยถึงจุดที่เป็นปัญหาในข้อเสนอการเปลี่ยน API และฟีดแบ็กนั้นได้นำไปสู่ข้อเสนอ ABI ใหม่ชื่อ abi4
  • Gross ได้สร้าง prototype ของ ABI ใหม่นี้แล้ว
  • Viktorin เห็นด้วยกับแนวทางโดยรวม แต่คิดว่ายังต้องเกลารายละเอียดเพิ่มเติม
  • Stinner มองว่าควรมี PEP สำหรับ abi4 และ Viktorin ก็รับเรื่องนี้ในฐานะการอภิปรายแบบ pre-PEP
  • มีความสับสนเกี่ยวกับการรับประกันความเข้ากันได้ที่เกิดจากการจับคู่ระหว่างเวอร์ชัน limited C API กับ abi3 และประเด็นนี้ก็ส่งผลต่อทิศทางของ abi4 ด้วย
  • การตรวจสอบที่เกี่ยวข้องยังดำเนินต่อไป และอาจมีการพูดคุยกันต่อแบบเจอหน้ากันใน core developer sprint ช่วงกลางเดือนตุลาคม

ถ้อยคำอนุมัติขั้นสุดท้ายและผลกระทบระยะยาว

  • งานพัฒนา no-GIL หรือ free-threaded CPython ยังเดินหน้าต่อ แต่การอนุมัติขั้นสุดท้ายของ PEP 703 ยังอยู่ระหว่างรอ
  • แม้ความล่าช้าจะยืดออกไปพอสมควร แต่ PEP 703 และผลกระทบต่อเนื่องของมันมีแนวโน้มจะส่งอิทธิพลอย่างมากต่อการพัฒนา CPython และระบบนิเวศในอีกกว่า 5 ปีข้างหน้า
  • steering council ต้องการทำให้เกณฑ์การอนุมัติชัดเจน
  • Thomas Wouters ระบุว่ากำลังเกลาถ้อยคำการอนุมัติที่แม่นยำ และต้องการทำให้การตัดสินใจหลายอย่างชัดเจนขึ้น
  • งานบางส่วนอาจดำเนินต่อในช่วง core developer sprint ด้วย

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

 
GN⁺ 2023-10-22
ความคิดเห็นจาก Hacker News
  • เมื่อมองดูคอมพิวเตอร์สมัยใหม่ ก็ทำให้นึกได้ว่า parallelism แบบชัดเจน อาจเป็นองค์ประกอบพื้นฐานของวิทยาการคอมพิวเตอร์มากกว่าที่นิยมพูดกันในตำรา
    ตอนนี้เราอาจมาถึงจุดที่ต้องเขียนโค้ดแบบขนานอย่างชัดเจนกันอยู่เสมอแล้วก็ได้

    • มนุษย์ไม่ค่อยเก่งในการให้เหตุผลกับหลายเธรดพร้อมกัน ดังนั้นการเปลี่ยนแปลงที่ใช้งานได้จริงกว่าน่าจะเป็นฝั่งของ ไวยากรณ์เชิงประกาศ ที่เราเริ่มเห็นกันแล้ว
      ตัวอย่างเช่นลูป for กำลังถูกแทนที่ด้วยโอเปอเรชันอย่าง foreach, map, filter นิพจน์แบบนี้บอกคอมไพเลอร์/อินเทอร์พรีเตอร์ว่าเราต้องการใช้การทำงานบางอย่างกับทุกองค์ประกอบในโครงสร้างข้อมูล แล้วปล่อยให้คอมไพเลอร์/รันไทม์ตัดสินใจว่าจะทำให้ขนานหรือไม่และอย่างไร
    • parallelism ได้แยกออกเป็นหลายทิศทาง
      ในการรันเว็บเซอร์วิส แต่ละรีเควสต์มักเร็วพออยู่แล้ว และประโยชน์ที่แท้จริงของ parallelism คือการจัดการหลายรีเควสต์พร้อมกัน ตรงนี้ No-GIL เข้ากันได้ดี
      ถ้าภายในรีเควสต์เดียวมีซับรีเควสต์จำนวนมาก ก็มักจัดการด้วยโค้ด async แต่หลายครั้งนั่นไม่ใช่เพราะ async ให้ประสิทธิภาพดีกว่า แต่อาจเพราะการสร้างเธรดมีต้นทุนสูงหรือการจัดการ thread pool ยุ่งยาก async ดีต่อ throughput แต่แย่ต่อ latency และถ้าคุณทำให้รีเควสต์ของเซอร์วิสขนานกัน โดยปกติคุณจะกังวลเรื่อง latency มากกว่า async ชนะมาได้ส่วนใหญ่เพราะใช้งานสะดวก
      parallelism อีกแบบหนึ่งเห็นได้ในงานออฟไลน์ขนาดใหญ่ เช่น MapReduce หรือ Presto ซึ่งโดยมากมีลักษณะเหมือนปัญหาแบบแบ่งแล้วพิชิต การฝึกโมเดลบน GPU ก็คล้ายกัน
      สิ่งที่ยังไม่เกิดขึ้นคืออัลกอริทึมแบบขนานสูงในเครื่องโลคัล สำหรับเว็บเซอร์วิส ขนาดข้อมูลเล็กเกินกว่าจะได้ประโยชน์ด้าน latency มากนัก การติดตั้งใช้งานซับซ้อน และต้นทุนการประสานงานระหว่างเธรดก็สูง ข้อยกเว้นเล็กน้อยคืออัลกอริทึมแบบ vectorized แต่สิ่งนี้รันบนคอร์เดียวจึงไม่มี overhead ด้านการประสานงาน และ online inference เองก็กลับมาเป็นงานที่ vectorized อย่างมากอีกเช่นกัน
    • ในวิทยาการคอมพิวเตอร์ parallelism คล้ายกับเรื่องความปลอดภัยอยู่บ้าง เรารู้ว่ามันสำคัญในเชิงนามธรรม แต่ถ้าจะเรียนให้ได้จริงก็ต้องไปฝึกเฉพาะทาง
      เมื่อเวลาผ่านไป ทั้งสองอย่างก็ดีขึ้นเรื่อย ๆ เหมือนกับที่ภาษาและไลบรารีจำนวนมากปลอดภัยโดยปริยายมากขึ้น ตอนนี้หลายอย่างก็ขนานได้โดยปริยายมากขึ้นเช่นกัน ยังไปไม่สุด แต่ก็ดีใจที่เราไม่ได้เริ่มกันเร็วเกินไป เพราะเทคโนโลยีในช่วง 10 ปีที่ผ่านมา ดีขึ้นมาก
      ตัวอย่างเช่น ลองเทียบสิ่งที่ทำได้อย่างปลอดภัยด้วย Rayon ของ Rust กับสิ่งที่เคยทำแบบไม่ปลอดภัยด้วย OpenMP ของ C++
      ด้านนอกออกไปอีกก็มีสิ่งที่ฉันทำงานอยู่ด้วย: https://legion.stanford.edu/, https://regent-lang.org/, https://github.com/nv-legate/cunumeric
    • ฉันมองว่า parallelism อยู่ในหมวดเดียวกับการจัดการหน่วยความจำ โปรแกรมส่วนใหญ่ที่เราเขียนสามารถใช้ การจัดการอัตโนมัติ ได้ไม่ทางใดก็ทางหนึ่ง และก็ควรเป็นแบบนั้น ส่วนการจัดการแบบแมนนวลก็ปล่อยไว้ในส่วนที่จำเป็นต่อประสิทธิภาพ
      เพราะมันเป็นรายละเอียดระดับ implementation ถ้าจะทำ abstraction ให้ใช้งานได้ง่ายขึ้นก็ควรทำ
    • ในวิกิของ LMAX Disruptor ระบุว่า latency เฉลี่ยในการส่งข้อความจากเธรดหนึ่งไปยังอีกเธรดหนึ่งคือ 53 นาโนวินาที
      ถ้าเทียบกัน mutex อยู่ที่ราว 25 นาโนวินาที และจะมากขึ้นเมื่อมี contention แต่ mutex เป็นการซิงโครไนซ์ระหว่างจุดต่อจุด
      ข้อดีของ Disruptor คือหลายเธรดสามารถรับข้อความเดียวกันได้โดยแทบไม่ต้องออกแรงเพิ่มมากนัก
      https://github.com/LMAX-Exchange/disruptor/wiki/Performance-...
      https://gist.github.com/rmacy/2879257
      ฉันใฝ่ฝันถึงภาษาที่คล้าย Smalltalk แต่ยังคงเป็น single-thread ไปจนกว่าการทำให้ขนานจะมีความหมาย
      ฉันกำลังมองหาปัญหา parallelism ที่ไม่ใช่บิ๊กดาต้า parallelism คล้ายกับการเอารถลงถนนเพิ่ม มากกว่าการทำให้รถวิ่งเร็วขึ้น แต่เรายังหากันอยู่ว่ามีงานอะไรบ้างที่ผู้ใช้เดสก์ท็อปหรือมือถือควรทำบนเครื่องโลคัลโดยใช้พลังด้านคณิตศาสตร์ของคอมพิวเตอร์
      ในแง่ไอเดียเรื่อง parallelism ฉันก็นึกถึงสถาปัตยกรรม Itanium และ VLIW ด้วย
  • ใช้ -ng ก็ได้ หมายถึง no-gil หรือ next-generation

    • ทำให้นึกถึงกระแสใหญ่ของการรองรับ Unix threading สมัยก่อน สิ่งที่นักพัฒนาต้องทำแตกต่างกันมหาศาลในแต่ละแพลตฟอร์ม
      มีทั้งแฟลกคอมไพเลอร์ใหม่ แฟลกลิงเกอร์ใหม่ การลิงก์ไลบรารีคนละชุด ไปจนถึงการใช้คำสั่งคอมไพล์คนละแบบโดยสิ้นเชิง AIX เป็นแบบนั้นชัดมาก
  • เรื่อง shebang น่าจะดีกว่าถ้าพึ่งพาธรรมเนียมเดิมของ Python: from __future__ import nogil
    จากนั้นก็ค่อย hot-swap อินเทอร์พรีเตอร์ ณ จุดนั้น

    • from __future__ import ไม่ใช่คำสั่งรันไทม์ แต่เป็น คำสั่งพิเศษ ที่ใช้แทนแฟลก
      https://docs.python.org/3/reference/simple_stmts.html#future...
    • “future statement เป็นคำสั่งถึงคอมไพเลอร์ให้คอมไพล์โมดูลหนึ่ง ๆ ด้วยไวยากรณ์หรือความหมายเชิง semantics ที่จะมีใช้ใน Python รุ่นอนาคต ซึ่งฟีเจอร์นั้นจะกลายเป็นมาตรฐาน”
      future statement ทำงานเป็นรายโมดูล และ GIL/no-GIL ก็ไม่ได้เข้ากับโมเดลนั้นได้ง่ายนัก
    • ถ้ามันไม่ได้ถูกรันเป็นโมดูลแรกและเป็น import ตัวแรก การติดตั้งใช้งานอาจกลายเป็นฝันร้ายได้
  • ทุกครั้งที่เห็นข้อเสนอนี้ก็อดสงสัยไม่ได้ว่าจะรับประกันอย่างไรให้โปรแกรมยังทำงานได้ถูกต้อง โค้ด Python แบบหลายเธรดที่มีอยู่เดิมจำนวนไม่น้อยเขียนมาอย่างไม่ปลอดภัย
    โดยเฉพาะปัญหา data race ที่เห็นซ้ำแล้วซ้ำเล่าทั้งในโค้ดเบสของหลายบริษัทและโปรเจ็กต์โอเพนซอร์ส โปรแกรมพวกนี้ยังไม่พังก็เพียงเพราะพึ่งพาโดยปริยายว่า GIL อนุญาตให้มีเพียงหนึ่งเธรดรันได้ในเวลาเดียวกัน
    ถ้า GIL หายไป โปรแกรมเหล่านี้ก็จะพัง Python เป็นภาษาแบบ dynamic type จึงน่าสงสัยมากว่าจะมี static analyzer ที่สามารถค้นหาปัญหาแบบนี้ในโปรแกรม Python เดิมได้หรือไม่
    สิ่งที่มีโอกาสเกิดขึ้นมากกว่าคือบั๊กที่แสดงตัวแบบไม่กำหนดแน่นอนในตอนรันไทม์และตรวจจับได้ยาก จะให้โปรแกรม crash ไปเลยยังดีกว่า แต่บั๊กประเภทนี้มีแนวโน้มจะนำไปสู่ผลลัพธ์ที่ทำงานผิดพลาดมากกว่า
    หรือบางทีข้อเสนอแบบไม่มี GIL นี้อาจไม่ได้ตั้งใจให้ใช้กับโปรแกรมส่วนใหญ่ก็ได้ มันอาจเป็นเครื่องมือเฉพาะทางมาก ๆ สำหรับบางกรณีเท่านั้น ที่โปรแกรมเมอร์รู้ว่าไม่มี GIL และเขียนโค้ดให้สอดคล้องกับมันได้

    • ถ้าเป็นโปรแกรมหลายเธรดที่มี data race อยู่แล้ว ก็ถือว่ามีปัญหาอยู่ก่อนแล้ว GIL ไม่ได้ทำให้ data race เป็นไปไม่ได้
      GIL หมายความแค่ว่าในช่วงเวลาใดเวลาหนึ่งจะมีได้เพียงหนึ่งเธรดที่รัน Python bytecode เท่านั้น อินเทอร์พรีเตอร์ที่มี GIL ก็ยังสลับเธรดระหว่าง bytecode ได้ และหลายโอเปอเรชันของ Python ต้องใช้หลาย bytecode รวมถึงเมธอดของ built-in type ที่หลายคนคิดว่าเป็น “atomic”
      เพราะแบบนั้น Python จึงมีสิ่งอย่าง lock, mutex, semaphore อยู่แล้วแม้ในปัจจุบันจะยังมี GIL ก็ตาม
    • เกร็ดเล็ก ๆ ที่น่าสนใจคือ GIL ไม่ได้ป้องกัน race condition bug ทุกอย่างได้เลย
      เธรดที่แย่ง GIL กันสามารถชิง GIL กันในจังหวะที่แย่ได้อยู่แล้วและทำให้เกิดความวุ่นวายได้
    • ประเด็นสำคัญคือให้ไลบรารีประกาศว่ารองรับ nogil mode หรือไม่ ซึ่งผมเข้าใจว่าเป็นแบบ opt-in
      ถ้าโปรแกรมจะรันโดยไม่มี GIL ได้ก็ต่อเมื่อ dependency ทั้งหมดอนุญาต แบบนั้นก็น่าจะมีเวลามากพอให้แก้บั๊กเหล่านี้
    • Python แบบ no-GIL อย่างเร็วที่สุดก็น่าจะมาอีกอย่างน้อยหลังผ่านไป 3~4 release cycle ตอนนี้ 3.11 ออกมาได้ 1 ปีแล้ว และโค้ด Python ในโปรดักชันจำนวนมากก็น่าจะยังอยู่แถว ๆ 3.8
      ถ้าอย่างนั้นกว่าปัญหานี้จะต้องรับมือกันในวงกว้างก็น่าจะใกล้ปี 2030 แล้ว ปกติก็แทบไม่เห็นโปรดักชันที่อัปเกรดรันไทม์ที่ใช้อยู่ไปเป็นรีลีสล่าสุดทันที
      ไม่ได้อยากพูดให้แรงเกินไป แต่ Steering Council ก็เคยบอกว่าไม่ต้องการให้เกิดการย้ายเวอร์ชันแบบ 2 ไป 3 อีกรอบ ดังนั้นคนคงไม่อัปเดตกันแบบสบายใจนัก และเนื้อหาส่วนใหญ่ที่มีอยู่บนอินเทอร์เน็ตตอนนี้ก็อาจเสี่ยงต่อการคัดลอกไปใช้ตรง ๆ
    • GIL ปกป้องแค่อินเทอร์พรีเตอร์เท่านั้น สิ่งที่มันทำได้ก็แค่ลดความถี่ของการเกิดปัญหา
      ในโค้ด Python จริง ๆ มีบั๊กเกี่ยวกับเธรดอยู่เยอะมาก
  • OCaml ก็ไม่ได้ผ่านวิวัฒนาการคล้าย ๆ กันหรอกหรือ? สงสัยว่ามีจุดไหนที่พอจะเปรียบเทียบกันได้ระหว่างสองโปรเจ็กต์นี้บ้าง

    • ผมว่าไม่เชิงแบบนั้น OCaml 5 ไม่ได้เอา global lock ออกแบบที่ทำให้โค้ดเดิมพัง แต่เพิ่ม primitive ใหม่ชื่อ domain เข้ามาแทน เพื่อจัดการหนึ่งเธรดขึ้นไปที่มี shared lock
      ดังนั้น API ของเธรดเดิมจึงสร้างเธรดภายใน domain ปัจจุบันได้ และสามารถแยกโค้ดที่คาดว่าจะมีการถือ lock ออกมาได้ โค้ดใหม่สามารถสร้าง domain ใหม่ที่เริ่มต้นด้วยเธรดเดียวแทนได้ และยังตั้งใจใช้สองอย่างนี้ร่วมกันในลักษณะของ scheduling ได้ด้วย
      ส่วน Python กำลังพยายามทำให้ lock กลายเป็นตัวเลือกแบบ global อย่างสมบูรณ์นอกเหนือการควบคุมของผู้เขียนไลบรารี แต่ดูเหมือนว่า lock ของ Python ถูกการันตีว่าใช้ปกป้องตัวรันไทม์เองเท่านั้น ดังนั้นโค้ดส่วนใหญ่ที่พึ่ง lock นี้ก็น่าจะมีบั๊กอยู่แล้ว และเพราะเหตุนี้แผนของ Python เองก็ดูพอเป็นไปได้
      ถ้าจะมีจุดร่วม ก็คงเป็นการต้องไล่หาและแก้ shared state ที่ไม่คาดคิดทั่วทั้งโค้ดเบสของรันไทม์ และต้องปรับปรุง C ABI
  • ตอนนี้ Python ก็มีโอกาสไล่ตาม Tcl ในด้านประสิทธิภาพแบบหลายเธรดแล้ว: https://www.hammerdb.com/blog/uncategorized/why-tcl-is-700-f...

  • ผมกลับอยากพอร์ตโค้ด Python ไป Mojo มากกว่า เพื่อให้ได้ multithreading, SIMD และการเพิ่มความเร็วแบบอื่น ๆ

    • คงจะดีถ้า Mojo อยู่ในโลกที่พัฒนามากกว่านี้ แต่ตอนนี้มันยังห่างจากจุดนั้นมาก
    • เห็นด้วย ผมยอมเขียนใหม่ด้วย Rust, Nim หรือ .NET ดีกว่า
    • การโดนดาวน์โหวตจนถึง -3 แสดงให้เห็นชัดเลยว่า HN downvote ไม่ได้เกี่ยวกับตรรกะ แต่เกี่ยวกับ การแย่งพื้นที่ และศักดิ์ศรี
      ไม่อยากย้ายโค้ด Python ไปเป็น nogil Python เหรอ? ถ้างั้นก็โดนดาวน์โหวต
  • ถ้าจะตั้งชื่อ ก็คงเป็น python4, python3-gilfoil, python3-gilfree อะไรทำนองนั้นได้

  • ตอนนี้รู้สึกว่ากระแสที่มุ่งไปที่ Python แบบไม่มี GIL ค่อนข้างแปลก ทีม Faster CPython ตั้งเป้าทะเยอทะยานไว้ว่าจะเพิ่มประสิทธิภาพของ CPython ขึ้น 50% ในทุกรีลีส
    ใน 3.11 มีการปรับปรุงจริง แต่ก็ยังห่างไกลจาก 50% มาก และในการทดสอบหลายชุดของเรา 3.12 ก็พอๆ กันหรือช้ากว่าด้วยซ้ำ การทำงานหลายเธรดอย่างแท้จริงคงยอดเยี่ยม แต่ก่อนอื่นผมอยากให้ ประสิทธิภาพแบบเธรดเดียว ดีขึ้นมากกว่า
    แน่นอนว่าก็ยอมรับได้ว่าความต้องการของเราอาจไม่ได้เป็นตัวแทนของทุกคน และขอบคุณสำหรับงานทั้งหมดที่ทำให้ Python เป็นภาษาที่ยอดเยี่ยม ถึงอย่างนั้นก็ยังสงสัยว่าผมกำลังมองข้ามอะไรไป

    • ผมคิดว่า Python จำเป็นต้องมีคำตอบเร่งด่วนสำหรับการใช้หลายคอร์ AMD เพิ่งเปิดตัว CPU 96 คอร์ ไปเอง
      ตอนนี้การใช้หลายคอร์ทำผ่าน multiprocessing ซึ่งมีข้อจำกัดเยอะ เข้าใจนะว่าอาจมีหลาย interpreter เข้ามาพร้อมสิ่งอย่าง coroutine ได้ แต่ถึงอย่างนั้นผมก็ยังชอบตัวเลือกแบบหลายเธรดจริงๆ มากกว่า
    • ทั้งสองอย่างเป็นเป้าหมายที่ต่างกันโดยสิ้นเชิง ตามทฤษฎีแล้ว Python แบบหลายเธรดอาจทำให้บางโปรแกรมเร็วขึ้นได้ แต่สิ่งสำคัญคือมันทำอย่างไร
      ใน nogil Python ยกตัวอย่างเช่น หลายเธรดสามารถเรียกโค้ด C พร้อมมี shared state ที่เข้าถึงได้ผ่านอ็อบเจ็กต์ Python นี่เป็นเรื่องค่อนข้างสำคัญสำหรับ แมชชีนเลิร์นนิง และจริงๆ แล้วรูปแบบปัจจุบันของ PEP นี้ก็มาจากทีม PyTorch
      ประสิทธิภาพแบบเธรดเดียวก็สำคัญ แต่สำหรับช่วงที่สำคัญอยู่แล้วก็มีทางอ้อมที่ค่อนข้างดีอย่าง numba, Cython และ Mojo
      ลำดับเวลาก็สำคัญ หากนำ nogil เข้ามา งานส่วนใหญ่ของ faster CPython อาจต้องถูกทิ้งไปทั้งหมด จึงต้องมีการประสานงานกันระหว่างทีม
      ในโลกอุดมคติ เราควรมีทั้งโหมด nogil และการปรับปรุงประสิทธิภาพแบบเธรดเดียว Guido เองก็ส่งสัญญาณว่ากำลังพิจารณา JIT ที่ซับซ้อนขึ้นด้วย
    • ส่วนที่มีต้นทุนการคำนวณสูงใน “Python” มักถูกจัดการโดยไลบรารีอย่าง numpy, tensorflow
      Python ทำให้การจัดการนามธรรมระดับล่างในภาษาที่ระดับสูงกว่าเป็นเรื่องสะดวกมาก ดังนั้นในฐานะนักพัฒนา Python มานาน ผมจึงไม่ได้เครียดกับ GIL มากนัก
    • ดูเหมือนคุณจะพลาดประเด็นที่ว่าความต้องการของคนที่ถูกอ้างถึงใน PEP 703 กับความต้องการของคุณนั้นต่างกัน: <https://peps.python.org/pep-0703/#motivation>
    • เท่าที่เข้าใจ ทั้งสองอย่างเป็นโปรเจ็กต์แยกกันภายใน CPython และก็ไม่จำเป็นว่าต้องเป็นคนกลุ่มเดียวกันที่ทำงาน
      ถ้าต้องเลือกอย่างใดอย่างหนึ่ง ผมเห็นด้วยว่าสำหรับกรณีใช้งานส่วนใหญ่ โค้ดแบบเธรดเดียวที่เร็วขึ้นน่าจะเหมาะกว่า แต่ก็ไม่มีเหตุผลว่าทำไมเราจะมีทั้งสองอย่างไม่ได้
  • มองย้อนกลับไปก็ชัดเจน แต่ถ้าฝั่ง Python รู้ว่าการเปลี่ยนจาก 2 ไป 3 จะยาวนานและเจ็บปวดขนาดไหน ก็น่าจะยกเครื่องภายใน interpreter ให้หนักกว่านี้มาก
    แม้ผ่านการเปลี่ยนผ่านที่ยาวถึง 12 ปี ประสิทธิภาพแบบเธรดเดียว ก็ยังแย่อยู่ และกว่าจะไปถึงการทำงานหลายเธรดอย่างแท้จริงก็ดูเหมือนยังมีการเปลี่ยนผ่านที่เจ็บปวดรออยู่อีกหลายครั้ง
    ผมรู้ว่าควรมีเมตตากับการพัฒนาโอเพนซอร์ส แต่ก็เริ่มสงสัยว่าถึงจุดไหนถึงจะเรียกได้ว่าเป็นภาษาที่บริหารจัดการได้แย่มาก

    • มันไม่ได้บริหารจัดการแย่หรอก Python มีปัญหาเยอะก็จริง แต่ทั้งหมดเป็นปัญหาที่เกิดจาก ความสำเร็จของ Python
      ส่วนที่แย่ที่สุดของ Python คือส่วนที่เปลี่ยนยากเพราะ Python ได้รับความนิยมมากเกินไปและ ecosystem ใหญ่มาก จึงทำให้การเปลี่ยนแปลงทุกแบบยากขึ้นเพราะต้องรักษาความเข้ากันได้ย้อนหลัง
    • ก็จริง ผ่านมาตั้งนานแล้ว multiprocessing ก็ยังแย่อยู่เหมือนเดิม
      คนมักปกป้อง Python เร็วเกินไป การมองแบบเป็นกลางและไม่ลำเอียงเป็นเรื่องสำคัญ
    • ถึงจุดหนึ่งน่าจะต้องสร้างภาษาใหม่ที่มีไวยากรณ์เหมือน Python แต่ถูกออกแบบมาตั้งแต่ต้นเพื่อประสิทธิภาพที่ดีกว่าและรองรับเธรดได้ดีกว่าไหม
      โปรเจ็กต์ที่ต้องการทั้งประสิทธิภาพและไวยากรณ์แบบ Python ก็ไปทางนั้นได้ ตอนนี้ Python ดูเหมือนกำลังดิ้นรนระหว่างหลายเป้าหมายและไปไม่ถึงสักอย่าง
    • ที่ว่าการเปลี่ยนจาก 2 ไป 3 จะยาวนานและเลวร้าย เป็นสิ่งที่คาดการณ์ได้ และในตอนนั้นคนก็พูดกันแบบนั้นอยู่แล้ว
      Perl 5/6 ถูกยกมาเป็นตัวอย่าง และแม้หลังจากชัดเจนแล้วว่าไม่มีใครย้ายตาม ก็ยังใช้เวลาอีกราว 5 ปีถึงจะมีความพยายามทำให้ย้ายได้ง่ายขึ้น