ทำไมงูหลามเขียนด้วย GIL


112

การล็อคล่ามทั่วโลก (GIL) ดูเหมือนจะถูกอ้างถึงบ่อยครั้งเป็นเหตุผลหลักว่าทำไมการทำเกลียวและสิ่งที่คล้ายกันนั้นเป็นเรื่องยุ่งยากใน Python ซึ่งทำให้เกิดคำถามขึ้นมาว่า

การเป็นโปรแกรมเมอร์ไม่ใช่ฉันไม่รู้ว่าทำไมอาจเป็น - อะไรคือเหตุผลที่อยู่เบื้องหลังในการวาง GIL?


10
บทความวิกิพีเดียระบุว่า"กิลอาจจะเป็นอุปสรรคสำคัญในการขนาน-ราคาที่จ่ายสำหรับการมีชีวิตชีวาของภาษา"และกล่าวต่อไปว่า"เหตุผลในการเช่นล็อครวมถึงความเร็วที่เพิ่มขึ้นของโปรแกรมเดียว threaded (ไม่จำเป็นต้องได้รับหรือปล่อยล็อคในโครงสร้างข้อมูลทั้งหมดแยกต่างหาก) และการรวมไลบรารี C ที่ง่ายซึ่งโดยทั่วไปจะไม่ปลอดภัยต่อเธรด "
Robert Harvey

3
@ RobertHarvey, Dynamism ไม่มีส่วนเกี่ยวข้องกับเรื่องนี้ ปัญหาคือการกลายพันธุ์
dan_waterworth


1
อดไม่ได้ที่จะรู้สึกว่าเหมือนตัวเลขที่ไม่ได้ลงนามของ Java มันมีจุดประสงค์เพื่อป้องกันไม่ให้คนที่ไม่รู้ว่ากำลังถ่ายทำอะไรอยู่ แต่น่าเสียดายที่คนที่ไม่ทราบว่าสิ่งที่พวกเขากำลังทำรับภาษาขาดซึ่งเป็นความอัปยศจริงเพราะหินงูใหญ่ในรูปแบบอื่น ๆ อีกมากมาย
Basic

1
@ พื้นฐานจะต้องมีวิธีมาตรฐานในการจัดการกับอาร์เรย์ไบต์ใน Java (ฉันไม่ได้ใช้มันมานาน) เพื่อที่จะทำ crypto math Python (ตัวอย่าง) ไม่มีหมายเลขที่เซ็นชื่อ แต่ฉันจะไม่ลองทำ bitwise ops ด้วยเพราะมีวิธีที่ดีกว่า
Nick T

คำตอบ:


105

มีการนำไปใช้งานหลายอย่างของ Python เช่น CPython, IronPython, RPython เป็นต้น

บางคนมี GIL แต่บางคนไม่มี ตัวอย่างเช่น CPython มี GIL:

จากhttp://en.wikipedia.org/wiki/Global_Interpreter_Lock

แอปพลิเคชันที่เขียนด้วยภาษาโปรแกรมด้วย GIL สามารถออกแบบให้ใช้กระบวนการแยกต่างหากเพื่อให้เกิดความขนานอย่างสมบูรณ์เนื่องจากแต่ละกระบวนการมีล่ามของตัวเองและในทางกลับกันก็มี GIL ของตัวเอง

ประโยชน์ของ GIL

  • เพิ่มความเร็วของโปรแกรมแบบเธรดเดียว
  • การรวมไลบรารี C ที่ง่ายซึ่งโดยทั่วไปจะไม่ปลอดภัยสำหรับเธรด

เหตุใด Python (CPython และอื่น ๆ ) จึงใช้ GIL

ใน CPython การล็อคตัวแปลภาษาทั่วโลกหรือ GIL เป็น mutex ที่ป้องกันไม่ให้เธรดหลายเธรดดำเนินการไพทอนของ Python พร้อมกัน การล็อกนี้เป็นสิ่งจำเป็นเนื่องจากการจัดการหน่วยความจำของ CPython ไม่ปลอดภัยสำหรับเธรด

GIL ขัดแย้งกันเนื่องจากป้องกันโปรแกรม CPython แบบมัลติเธรดจากการใช้ประโยชน์เต็มที่จากระบบมัลติโปรเซสเซอร์ในบางสถานการณ์ โปรดทราบว่าอาจมีการบล็อกหรือการทำงานที่ยาวนานเช่น I / O การประมวลผลภาพและการบีบอัดตัวเลข NumPy ซึ่งเกิดขึ้นนอก GIL ดังนั้นจึงมีเฉพาะในโปรแกรมแบบมัลติเธรดที่ใช้เวลาส่วนใหญ่ใน GIL ​​ตีความ CPTC bytecode ว่า GIL กลายเป็นคอขวด

Python มี GIL ซึ่งต่างจากการล็อกแบบละเอียดด้วยเหตุผลหลายประการ:

  • มันเร็วกว่าในเคสแบบเธรดเดี่ยว

  • จะเร็วกว่าในกรณีแบบมัลติเธรดสำหรับโปรแกรมที่ถูกผูกไว้ของ i / o

  • มันเร็วกว่าในกรณีแบบมัลติเธรดสำหรับโปรแกรมที่เชื่อมโยงกับ cpu ซึ่งทำงานที่ต้องใช้การคำนวณอย่างมากในไลบรารี C

  • มันทำให้ส่วนขยาย C ง่ายต่อการเขียน: จะไม่มีสวิตช์ของเธรด Python ยกเว้นตำแหน่งที่คุณอนุญาตให้เกิดขึ้น (เช่นระหว่าง Py_BEGIN_ALLOW_THREADS และ Py_END_ALLOW_THREADS มาโคร)

  • มันทำให้การห่อ C ไลบรารีง่ายขึ้น คุณไม่ต้องกังวลกับหัวข้อความปลอดภัย หากไลบรารีไม่ปลอดภัยสำหรับเธรดคุณเพียงแค่ล็อค GIL ไว้ในขณะที่คุณเรียกมัน

GIL สามารถเผยแพร่โดยส่วนขยาย C ไลบรารี่มาตรฐานของ Python จะปล่อย GIL รอบ ๆ การบล็อกแต่ละครั้งที่ฉันโทรเข้า ดังนั้น GIL ​​จึงไม่มีผลต่อประสิทธิภาพของเซิร์ฟเวอร์ที่เชื่อมโยงกับ i / o คุณสามารถสร้างเซิร์ฟเวอร์เครือข่ายใน Python โดยใช้โพรเซส (ทางแยก), เธรดหรืออะซิงโครนัส i / o, และ GIL จะไม่เข้าทางคุณ

ไลบรารีตัวเลขใน C หรือ Fortran สามารถถูกเรียกในทำนองเดียวกันเมื่อ GIL เผยแพร่ ในขณะที่ส่วนขยาย C ของคุณกำลังรอให้ FFT เสร็จสมบูรณ์ล่ามจะดำเนินการเธรด Python อื่น ๆ GIL นั้นง่ายกว่าและเร็วกว่าการล็อคแบบละเอียดในกรณีนี้เช่นกัน นี่ถือเป็นการทำงานที่เป็นตัวเลข ส่วนขยาย NumPy จะปล่อย GIL เมื่อทำได้

เธรดมักเป็นวิธีที่ไม่ดีในการเขียนโปรแกรมเซิร์ฟเวอร์ส่วนใหญ่ หากโหลดต่ำการฟอร์กก็จะง่ายขึ้น ถ้าโหลดสูงอะซิงโครนัส i / o และการเขียนโปรแกรมที่ขับเคลื่อนด้วยเหตุการณ์ (เช่นใช้เฟรมเวิร์ก Twisted Python) จะดีกว่า ข้อแก้ตัวสำหรับการใช้เธรดเท่านั้นคือการขาด os.fork บน Windows

GIL เป็นปัญหาหากและถ้าคุณกำลังทำงาน CPU-intensive ใน Python บริสุทธิ์ ที่นี่คุณสามารถออกแบบที่สะอาดขึ้นโดยใช้กระบวนการและการส่งข้อความ (เช่น mpi4py) นอกจากนี้ยังมีโมดูล 'การประมวลผล' ในร้านค้า Python cheese ที่ให้กระบวนการกับส่วนต่อประสานกับเธรด (เช่นแทนที่เธรดเธรดด้วยการประมวลผลกระบวนการ)

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


52
เสียงเหมือนองุ่นเปรี้ยวสำหรับฉัน Python ไม่สามารถทำเธรดได้อย่างถูกต้องดังนั้นคุณต้องคำนึงถึงเหตุผลว่าทำไมเธรดจึงไม่จำเป็นหรือไม่ดี "ถ้าโหลดต่ำการฟอร์กก็ง่ายกว่า" ใช่ไหม? และ GIL นั้น "เร็วกว่า" สำหรับกรณีเหล่านี้ทั้งหมดต่อเมื่อคุณยืนยันที่จะใช้การนับ GC อ้างอิงเท่านั้น
Michael Borgwardt

9
s/RPython/PyPy/g. @MichaelBorgwardt การให้เหตุผลกับมืออาชีพ GIL เป็นประเด็นของคำถามใช่มั้ย แม้ว่าฉันจะยอมรับว่าเนื้อหาบางส่วนของคำตอบนี้ (กล่าวคือการอภิปรายทางเลือก) อยู่ด้านข้างจุด และสำหรับดีขึ้นหรือแย่ลง refcounting ตอนนี้แทบเป็นไปไม่ได้ที่จะกำจัด - มันฝังลึกอยู่ใน API และฐานรหัสทั้งหมด แทบจะเป็นไปไม่ได้เลยที่จะกำจัดมันออกไปโดยไม่ต้องเขียนโค้ดครึ่งหนึ่งแล้วทำลายรหัสภายนอกทั้งหมด

10
อย่าลืมmultiprocessingห้องสมุด - มาตรฐานตั้งแต่ 2.6 มันเป็นกลุ่มคนทำงานที่เป็นนามธรรมที่ลื่นไหลสำหรับการขนานที่เรียบง่ายบางประเภท
Sean McSomething

8
@alcalde เฉพาะในกรณีที่คุณไม่ทราบว่าคุณกำลังทำอะไรอยู่และ / หรือคุณไม่ต้องการให้เธรดของคุณทำงานร่วมกัน / สื่อสารได้ มิฉะนั้นมันเป็นความเจ็บปวดในด้านหลังโดยเฉพาะอย่างยิ่งการพิจารณาค่าใช้จ่ายในการเปิดตัวกระบวนการใหม่ในบางระบบปฏิบัติการ เรามีเซิร์ฟเวอร์ที่มี 32 คอร์ดังนั้นเพื่อใช้ประโยชน์อย่างเต็มที่ใน CPython ฉันต้องการ 32 โพรเซส นั่นไม่ใช่ "วิธีแก้ปัญหาที่ดี" แต่เป็นแฮ็คที่ใช้แก้ไขข้อบกพร่องของ CPython
พื้นฐาน

8
ข้อเท็จจริงที่ว่ามีเธรดอยู่บนแพลตฟอร์มอื่นที่ไม่ใช่ Windows ควรมีหลักฐานเพียงพอว่าการฟอร์กนั้นไม่เพียงพอในทุกสถานการณ์
zneak

42

ก่อนปิด: Python ไม่มี GIL Python เป็นภาษาโปรแกรม ภาษาการเขียนโปรแกรมเป็นชุดของกฎและข้อ จำกัด ทางคณิตศาสตร์ที่เป็นนามธรรม ไม่มีอะไรใน Python Language Specification ที่บอกว่าต้องมี GIL

Python มีการนำไปใช้ที่แตกต่างกันมากมาย บางคนมี GIL บางคนไม่มี

คำอธิบายง่ายๆสำหรับการมี GIL คือการเขียนโค้ดพร้อมกันนั้นยาก ด้วยการวางกุญแจขนาดใหญ่ไว้รอบ ๆ รหัสของคุณคุณบังคับให้มันทำงานแบบต่อเนื่องทุกครั้ง แก้ไขปัญหา!

โดยเฉพาะอย่างยิ่งใน CPython เป้าหมายสำคัญอย่างหนึ่งคือทำให้การขยายล่ามด้วยปลั๊กอินที่เขียนด้วยภาษาซีอีกครั้งการเขียนโค้ดที่ใช้งานพร้อมกันนั้นทำได้ยากดังนั้นโดยการรับประกันว่าจะไม่มีการทำงานพร้อมกันทำให้การเขียนส่วนขยายสำหรับ ล่าม นอกจากนี้ส่วนขยายเหล่านั้นจำนวนมากเป็นเพียงตัวย่อบาง ๆ รอบ ๆ ไลบรารีที่มีอยู่ซึ่งอาจไม่ได้เขียนด้วยใจพร้อมกัน


6
นั่นเป็นเหตุผลเดียวกับที่ Java ขาดประเภทตัวเลขที่ไม่ได้ลงนาม - นักพัฒนาคิดว่าคนอื่นโง่กว่าพวกเขา ...
พื้นฐาน

1
@Basic - เชื่อหรือไม่แม้ว่าคุณจะไม่ได้โง่จริง ๆ มันกลับกลายเป็นว่าการมีภาษาที่ทำให้สมมติฐานง่ายขึ้นซึ่งหมายความว่าคุณไม่ได้คิดถึงบางสิ่งบางอย่างเพื่อให้การทำงานยังคงมีประโยชน์ สิ่ง. CPython นั้นยอดเยี่ยมสำหรับบางสิ่งรวมถึงแอพพลิเคชั่นแบบมัลติเธรดที่เรียบง่าย (ซึ่งโปรแกรมนั้นถูกผูกไว้กับ IO ซึ่งหลาย ๆ ตัวและดังนั้น GIL ​​ไม่สำคัญ) เนื่องจากการตัดสินใจออกแบบที่ทำให้ GIL เป็นทางออกที่ดีที่สุด โดยเฉพาะอย่างยิ่งความจริงที่ว่าจะสนับสนุนการดำเนินงานของอะตอมในคอลเลกชัน
จูลส์

@Jules ใช่มันมีประโยชน์มากจนกระทั่งคุณต้องการความสามารถเหล่านั้น cpython "ที่ต้องการ" ทางออกของ "เพียงแค่เขียนในภาษาอื่นเช่น c ++" แล้วหมายความว่าคุณสูญเสียผลประโยชน์หลามทุกอย่างโดยลำพัง หากคุณกำลังเขียนโค้ดครึ่งหนึ่งใน c ++ ดังนั้นทำไมเริ่มจาก Python แน่นอนว่าสำหรับโครงการ API / กาวขนาดเล็กมันง่ายและรวดเร็วและสำหรับ ETL นั้นไม่เป็นสองรองใคร แต่ไม่เหมาะสำหรับทุกสิ่งที่ต้องยกของหนัก เหมือนกับการใช้จาวาเพื่อพูดคุยกับฮาร์ดแวร์ ... มันเป็นเรื่องตลกที่คุณต้องข้าม
พื้นฐาน

16

จุดประสงค์ของ GIL คืออะไร?

เอกสารของ CAPI มีไว้เพื่อพูดในเรื่อง:

Python interpreter ไม่ปลอดภัยสำหรับเธรดอย่างสมบูรณ์ เพื่อสนับสนุนโปรแกรม Python แบบมัลติเธรดมีการล็อกแบบโกลบอลเรียกว่าล็อกการแปลระดับโลกหรือ GIL ที่จะต้องถูกจัดเก็บโดยเธรดปัจจุบันก่อนที่จะสามารถเข้าถึงวัตถุ Python ได้อย่างปลอดภัย หากไม่มีการล็อกแม้การดำเนินการที่ง่ายที่สุดอาจทำให้เกิดปัญหาในโปรแกรมแบบมัลติเธรด: ตัวอย่างเช่นเมื่อสองเธรดเพิ่มจำนวนการอ้างอิงของวัตถุเดียวกันพร้อมกันจำนวนการอ้างอิงอาจสิ้นสุดลงด้วยการเพิ่มขึ้นเพียงครั้งเดียวแทนที่จะเป็นสองครั้ง

กล่าวอีกนัยหนึ่ง GIL คือการป้องกันการทุจริตของรัฐ โปรแกรม Python ไม่ควรสร้างความผิดพลาดในการแบ่งเซกเมนต์เพราะอนุญาตให้ใช้งานได้อย่างปลอดภัยเท่านั้น GIL ขยายการรับประกันนี้ไปยังโปรแกรมแบบมัลติเธรด

ทางเลือกคืออะไร?

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


2
มันจะเป็นการดีถ้าให้ผู้ใช้เรียกใช้โปรแกรมด้วยตัวเลือกล่ามแทน gil สำหรับการล็อกแบบละเอียดและอย่างใดทราบว่าเป็นแบบอ่านอย่างเดียว - ไม่ว่ากระบวนการปัจจุบันจะถูกเพิ่มด้วยหรือไม่มี gil
Luis Masuelli

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