PyPy - จะเอาชนะ CPython ได้อย่างไร


264

จากบล็อก Google Open Source :

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

เป็นไปได้อย่างไร? การใช้ Python แบบใดที่จะใช้ PyPy CPython ? และโอกาสของ PyPyPy หรือ PyPyPyPy จะทำคะแนนได้อย่างไร

(ในบันทึกที่เกี่ยวข้อง ... ทำไมทุกคนจะลองแบบนี้)


43
Nitpick: PyPy คือ PyPyPy คิดว่าคำนำหน้า Py- * เป็นตัวดำเนินการฉายภาพ
u0b34a0f6ae

ตกลง. ดังนั้นควรใช้ PyPy มากกว่า CPython หรือไม่ มันมีข้อบกพร่องหรือไม่?
balki

10
PyPy นั้นยอดเยี่ยมในการเพิ่มประสิทธิภาพรันไทม์ แต่อวัยวะภายในที่แตกต่างกันทำให้เข้ากันไม่ได้กับส่วนขยาย C ยอดนิยมหลายรายการ
Cees Timmerman

4
เกือบทุกคนไม่มีคำถามว่าการเพิ่มความเร็วนั้นเป็นไปได้ในทางทฤษฎี แต่ลองคิดดูสิ: Python สามารถทำอะไรก็ได้เหมือนกับเครื่องจักรทัวริง มันสามารถโทรหาgccหลังจากทั้งหมด ดังนั้นคุณสามารถเขียนโค้ดไพ ธ อนบางตัวที่รันบน CPython ซึ่งตีความโค้ดไพ ธ อนอื่น ๆ แปลเป็น C และดำเนินการgccแล้วรันโปรแกรมที่คอมไพล์แล้ว และมันอาจจะเร็วกว่านี้ถ้ารหัสนั้นถูกเรียกใช้บ่อยเพียงพอ
osa

คำตอบ:


155

ไตรมาสที่ 1 เป็นไปได้อย่างไร?

การจัดการหน่วยความจำด้วยตนเอง (ซึ่งเป็นสิ่งที่ CPython ทำกับการนับ) อาจช้ากว่าการจัดการอัตโนมัติในบางกรณี

ข้อ จำกัด ในการใช้งานล่าม CPython จะแยกแยะการเพิ่มประสิทธิภาพบางอย่างที่ PyPy สามารถทำได้ (เช่นการล็อคเม็ดเล็กละเอียด)

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

ไตรมาสที่ 2 การใช้ Python แบบใดที่จะใช้ PyPy

PyPy interpreter ถูกนำไปใช้ใน RPython ซึ่งเป็นชุดย่อยของ Python ที่เป็นแบบสแตติก (เป็นภาษาและไม่ใช่ CPython interpreter) - อ้างอิงhttps://pypy.readthedocs.org/en/latest/architecture.htmlเพื่อดูรายละเอียด

ไตรมาสที่ 3 และโอกาสของ PyPyPy หรือ PyPyPyPy คือการทำคะแนนของพวกเขา?

ที่จะขึ้นอยู่กับการใช้งานของล่ามสมมุติฐานเหล่านี้ ถ้าอย่างใดอย่างหนึ่งของพวกเขาเอาแหล่งที่มาได้ทำการวิเคราะห์บางอย่างบนมันและแปลงเป็นรหัสแอสเซมบลีเฉพาะเป้าหมายแน่นหลังจากเรียกใช้ในขณะที่ฉันคิดว่ามันจะเร็วกว่า CPython

ปรับปรุง:เมื่อเร็ว ๆ นี้ในตัวอย่างที่สร้างขึ้นอย่างระมัดระวัง , PyPy เฮงโปรแกรม C gcc -O3ที่คล้ายกันรวบรวมกับ มันเป็นกรณีที่วางแผนไว้ แต่แสดงความคิดบางอย่าง

ไตรมาสที่ 4 ทำไมทุกคนจะลองแบบนี้

จากเว็บไซต์อย่างเป็นทางการ https://pypy.readthedocs.org/en/latest/architecture.html#mission-statement

เรามุ่งมั่นที่จะให้:

  • แปลทั่วไปและกรอบการสนับสนุนสำหรับการผลิต
    การใช้งานภาษาแบบไดนามิกเน้นการทำความสะอาด
    แยกระหว่างข้อกำหนดภาษาและการดำเนินงาน
    ด้าน เราเรียกสิ่งนี้RPython toolchainว่า

  • การใช้งาน Python_ Language ที่สอดคล้องยืดหยุ่นและรวดเร็วซึ่งใช้ toolchain ด้านบนเพื่อเปิดใช้งานฟีเจอร์ขั้นสูงระดับสูงใหม่โดยไม่ต้องเข้ารหัสรายละเอียดระดับต่ำ

ด้วยการแยกข้อกังวลด้วยวิธีนี้การใช้ Python และภาษาไดนามิกอื่น ๆ ของเราสามารถสร้างคอมไพเลอร์ Just-in-Time สำหรับภาษาแบบไดนามิกใด ๆ โดยอัตโนมัติ นอกจากนี้ยังอนุญาตให้มีการผสมผสานการจับคู่กับการตัดสินใจในการนำไปใช้งานซึ่งรวมถึงการตัดสินใจหลายอย่างที่ไม่เคยมีมาก่อนในการควบคุมของผู้ใช้เช่นแพลตฟอร์มเป้าหมายหน่วยความจำและแบบจำลองเกลียวกลยุทธ์การเก็บขยะและการปรับให้เหมาะสม JIT ตั้งแต่แรก

คอมไพเลอร์ Gcc gcc ถูกนำมาใช้ใน C, คอมไพเลอร์ Haskell GHC ถูกเขียนใน Haskell คุณมีเหตุผลใดที่ Python interpreter / compiler จะไม่ถูกเขียนใน Python หรือไม่?


82
คำตอบนี้หายไปอย่างสมบูรณ์คำอธิบายหลักสำหรับวิธีการที่รวดเร็ว PyPy; ในขณะที่กล่าวถึงว่า PyPy ไม่ได้ถูกนำมาใช้จริงใน Python แต่ใน RPython มันไม่ได้ชี้ให้เห็นว่ารหัส RPython นั้นถูกรวบรวมแบบคงที่และปรับให้เหมาะสมในการผลิต PyPy ล่าม (มันเพิ่งเกิดขึ้นกับรหัส Python ที่ถูกต้อง ของ CPython ช้ากว่ามาก) สิ่งที่พวกเขานำมาใช้ใน "ไพ ธ อนปกติ" คือคอมไพเลอร์ RPython "(เฟรมเวิร์กการแปลที่อ้างถึงในเครื่องหมายคำพูดบล็อก)
Ben

12
นี่คือการฝัง lede ประสิทธิภาพส่วนใหญ่มาจากการแปลเป็น C (ซึ่งทำให้ล่ามนั้นไม่ช้ากว่า CPython มาก) และ JIT ซึ่งทำให้เส้นทางร้อนแรงเร็วกว่ามาก
Tobu

4
"อัปเดต: เมื่อเร็ว ๆ นี้ในตัวอย่างที่ออกแบบมาอย่างพิถีพิถัน PyPy มีประสิทธิภาพดีกว่าโปรแกรม C ที่คล้ายกันซึ่งคอมไพล์ด้วย gcc -O3" และถ้าคุณอ่านความคิดเห็นแรกภายใต้โพสต์นั้นคุณจะเห็นว่าผู้เขียนโพสต์นั้นไม่ทราบว่าการเพิ่มประสิทธิภาพเวลาลิงค์ เมื่อเปิดใช้งานการเพิ่มประสิทธิภาพลิงค์เวลารหัส C จะทำงานได้เร็วขึ้น
อาลี

2
บล็อกโพสต์ในปี 2011 และคำตอบนี้ในปี 2014 นอกจากนี้ความคิดเห็นไม่พูดถึงห้องสมุดสาธารณะที่ใช้ร่วมกัน ฉันไม่รู้ว่าสิ่งนี้ (คำตอบและโพสต์บล็อก) นี้ถูกต้อง เทคโนโลยีที่เกี่ยวข้องทั้งหมดเปลี่ยนแปลงไปมากในช่วงไม่กี่ปีที่ผ่านมา
Noufal Ibrahim

1
ในตัวอย่าง Pypy ที่สร้างขึ้นอย่างรอบคอบทั้งสองอย่างนั้นเร็วกว่า C ที่เท่ากันแต่ละตัวนั้นเร็วกว่าในการกำหนดมาตรฐานด้วยเหตุผลที่เฉพาะเจาะจง ครั้งแรกเพราะ Pypy ฉลาดพอที่จะตระหนักถึงการนับจำนวนวงที่ไม่เคยใช้ดังนั้นจึงสามารถลบได้ทั้งหมด (JIT Pass) อันดับที่สองสำหรับการรวมกัน: เนื่องจาก Pypy JIT สามารถ "อินไลน์ข้ามขอบเขตห้องสมุด" ได้ ตัวอย่างของฟังก์ชั่น "printf" ที่มีความสามารถเฉพาะในการปล่อยจำนวนเต็มเท่านั้นและกำจัด malloc ที่ซ้ำกัน (ค่าใช้จ่ายในการจัดสรรหน่วยความจำ) ซ้ำ
รวบรวม

291

"PyPy เป็นการปรับใช้ Python ใน Python อีกครั้ง" เป็นวิธีที่ค่อนข้างหลอกลวงในการอธิบาย PyPy, IMHO แม้ว่ามันจะเป็นเทคนิคจริงก็ตาม

PyPy มีสองส่วนหลัก

  1. กรอบการแปล
  2. ล่าม

กรอบการแปลเป็นคอมไพเลอร์ มันรวบรวมรหัสRPythonลงไปที่ C (หรือเป้าหมายอื่น ๆ ) โดยอัตโนมัติเพิ่มในด้านต่าง ๆ เช่นการเก็บขยะและคอมไพเลอร์ JIT มันไม่สามารถจัดการรหัส Python ได้เองโดยเฉพาะ RPython

RPython เป็นชุดย่อยของ Python ปกติ รหัส RPython ทั้งหมดเป็นรหัส Python แต่ไม่ใช่รหัสอื่น ๆ ไม่มีคำจำกัดความที่เป็นทางการของ RPython เนื่องจาก RPython เป็นเพียง "ชุดย่อยของ Python ที่สามารถแปลได้โดยกรอบการแปลของ PyPy" แต่เพื่อที่จะได้รับการแปลรหัส RPython จะต้องพิมพ์แบบคงที่ (ประเภทที่อนุมานคุณไม่ได้ประกาศ แต่ก็ยังคงประเภทหนึ่งต่อตัวแปรอย่างเคร่งครัด) และคุณไม่สามารถทำสิ่งต่าง ๆ เช่นประกาศ / แก้ไขฟังก์ชั่น / คลาสที่รันไทม์อย่างใดอย่างหนึ่ง

ล่ามนั้นเป็นล่าม Python ปกติที่เขียนใน RPython

เนื่องจากรหัส RPython เป็นรหัส Python ปกติคุณจึงสามารถเรียกใช้บนตัวแปล Python ใด ๆ แต่ความเร็วของ PyPy นั้นไม่ได้มาจากการวิ่ง นี้เป็นเพียงสำหรับรอบการทดสอบอย่างรวดเร็วเพราะแปลล่ามใช้เวลานานเวลา

ด้วยความเข้าใจนั้นควรเห็นได้อย่างชัดเจนในทันทีว่าการคาดเดาเกี่ยวกับ PyPyPy หรือ PyPyPyPy ไม่สมเหตุสมผลจริง ๆ คุณมีล่ามเขียนไว้ใน RPython คุณแปลเป็นรหัส C ซึ่งดำเนินการ Python อย่างรวดเร็ว กระบวนการหยุดลงที่นั่น ไม่มี RPython ที่จะเร่งความเร็วโดยประมวลผลอีกครั้ง

ดังนั้น "เป็นไปได้อย่างไรที่ PyPy จะเร็วกว่า CPython" จึงกลายเป็นสิ่งที่ค่อนข้างชัดเจนเช่นกัน PyPy มีการนำไปใช้ที่ดีขึ้นรวมถึง JIT คอมไพเลอร์ (โดยทั่วไปจะไม่เร็วเท่านี้หากไม่มี JIT คอมไพเลอร์ฉันเชื่อว่าซึ่งหมายความว่า PyPy นั้นเร็วกว่าเฉพาะโปรแกรมที่ไวต่อการรวบรวม JIT) CPython ไม่เคยได้รับการออกแบบให้ใช้งานภาษา Python ให้เกิดประโยชน์สูงสุด (แม้ว่าพวกเขาจะพยายามทำให้เป็นการนำไปใช้ที่มีประสิทธิภาพสูงสุดหากคุณทำตามความแตกต่าง)


บิตที่แปลกใหม่ของโปรเจค PyPy คือพวกเขาไม่ได้เขียนโครงร่าง GC ที่ซับซ้อนหรือคอมไพเลอร์ JIT ด้วยมือ พวกเขาเขียนล่ามค่อนข้างตรงไปตรงมาใน RPython และสำหรับ RPython ทั้งหมดนั้นอยู่ในระดับที่ต่ำกว่า Python มันยังคงเป็นภาษาที่รวบรวมขยะเชิงวัตถุซึ่งมีระดับสูงกว่า C มากดังนั้นกรอบการแปลจะเพิ่มสิ่งต่าง ๆ เช่น GC และ JIT โดยอัตโนมัติ ดังนั้นกรอบการแปลจึงมีขนาดใหญ่มากความพยายาม แต่มันใช้กับตัวแปล PyPy python ได้ดีพอ ๆ กัน แต่พวกมันเปลี่ยนการใช้งานทำให้มีอิสระมากขึ้นในการทดลองเพื่อปรับปรุงประสิทธิภาพ (โดยไม่ต้องกังวลกับการแนะนำข้อบกพร่อง GC หรือปรับปรุง JIT คอมไพเลอร์เพื่อรับมือกับการเปลี่ยนแปลง) นอกจากนี้ยังหมายถึงเมื่อพวกเขาได้ใช้งานล่าม Python3 ก็จะได้รับประโยชน์โดยอัตโนมัติ และล่ามอื่น ๆ ที่เขียนด้วยกรอบ PyPy (ซึ่งมีจำนวนในขั้นตอนการขัดที่แตกต่างกัน) และล่ามทั้งหมดที่ใช้เฟรมเวิร์ก PyPy จะสนับสนุนแพลตฟอร์มทั้งหมดที่สนับสนุนโดยเฟรมเวิร์กโดยอัตโนมัติ

ดังนั้นประโยชน์ที่แท้จริงของโครงการ PyPy คือการแยกส่วนต่าง ๆ ทั้งหมดของการใช้ล่ามที่ไม่ขึ้นกับแพลตฟอร์มที่มีประสิทธิภาพสำหรับภาษาแบบไดนามิก และจากนั้นเกิดการใช้งานที่ดีเพียงครั้งเดียวในที่เดียวซึ่งสามารถนำมาใช้ซ้ำได้กับล่ามหลายคน นี่ไม่ใช่การชนะอย่างทันทีทันใดเช่น "โปรแกรม Python ของฉันทำงานเร็วขึ้น" แต่มันเป็นโอกาสที่ดีสำหรับอนาคต

และสามารถเรียกใช้โปรแกรม Python ของคุณได้เร็วขึ้น (อาจ)


4
ฉันแบ่งความแตกต่างไม่ได้ :(
polvoazul

37
@polvoazul ความแตกต่างระหว่างการปรับใช้ภาษาที่ได้รับการปรับให้เหมาะสมและการปรับให้เหมาะสมหรือไม่ เมื่อฉันบอกว่า CPython เป็นการใช้งานที่ดีที่สุดฉันหมายถึงนักพัฒนาพยายามที่จะทำให้อัลกอริธึมภายในของตัวแปลเองและโครงสร้างข้อมูลภายในทำงานได้อย่างมีประสิทธิภาพ การปรับใช้ให้เกิดประโยชน์สูงสุด OTOH จะวิเคราะห์รหัสผู้ใช้ปลายทางและพยายามหาวิธีในการแปลงมันให้ทำงานได้อย่างมีประสิทธิภาพมากขึ้น
Ben

23

PyPy ถูกนำมาใช้ใน Python แต่ใช้คอมไพเลอร์ JIT เพื่อสร้างโค้ดเนทีฟแบบทันที

เหตุผลในการนำ PyPy มาใช้บน Python นั้นอาจเป็นเพียงภาษาที่มีประสิทธิภาพมากโดยเฉพาะอย่างยิ่งเนื่องจากคอมไพเลอร์ JIT ทำให้ประสิทธิภาพของภาษาโฮสต์ค่อนข้างไม่เกี่ยวข้อง


JIT สร้างโค้ด Python ที่รันในระดับเดียวกับ PyPy หรือสร้างโค้ดเนทีฟจริงที่รันในระดับใดก็ตามที่ Python ใช้งาน PyPy ทำงานอยู่หรือไม่?
Edmund

3
รหัสพื้นเมืองจริง (ดูที่นี่ ); รหัส x86 แบบ 32 บิตต้องแม่นยำ
Marcelo Cantos

11

PyPy เขียนใน Python ที่ถูก จำกัด มันไม่ทำงานบนล่าม CPython เท่าที่ฉันรู้ Python ที่ถูก จำกัด เป็นชุดย่อยของภาษา Python AFAIK ตัวแปล PyPy ถูกคอมไพล์ไปยังรหัสเครื่องดังนั้นเมื่อติดตั้งแล้วจะไม่ใช้ตัวแปลหลามในตอนรันไทม์

คำถามของคุณดูเหมือนจะคาดหวังว่าล่าม PyPy กำลังทำงานอยู่ด้านบนของ CPython ในขณะที่รันโค้ด แก้ไข:ใช่เพื่อใช้ PyPy ก่อนอื่นคุณต้องแปลรหัส PyPy python เป็น C และ build ด้วย gcc, เป็น jvm byte code หรือเป็นรหัส. NET CLI ดูการเริ่มต้น


8
PyPy จะทำงานบน CPython แต่ในโหมดนี้มันไม่ได้ให้ความเร็วที่ใคร ๆ ก็อยากได้ :-) codespeak.net/pypy/dist/pypy/doc/…
Frank V
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.