เหตุใดจึงไม่มีคอมไพเลอร์หลามในรหัสเครื่องดั้งเดิม


25

ดังที่ฉันเข้าใจสาเหตุของความแตกต่างของความเร็วระหว่างภาษาที่คอมไพล์และไพ ธ อนนั้นคือคอมไพล์รหัสแรกไปจนถึงรหัสของเครื่องเนทีฟในขณะที่ไพ ธ อนคอมไพล์ไปยัง python bytecode เพื่อตีความโดย PVM ฉันเห็นว่าวิธีการใช้รหัสหลามบนระบบปฏิบัติการหลายระบบ (อย่างน้อยในกรณีส่วนใหญ่) แต่ฉันไม่เข้าใจว่าทำไมไม่มีคอมไพเลอร์เพิ่มเติม (และเป็นทางเลือก) สำหรับไพ ธ อนซึ่งคอมไพล์เช่นเดียวกับคอมไพเลอร์แบบดั้งเดิม . สิ่งนี้จะทำให้โปรแกรมเมอร์เลือกซึ่งมีความสำคัญต่อพวกเขามากกว่า ความสามารถในการปฏิบัติงานแบบหลายแพลตฟอร์มหรือประสิทธิภาพบนเครื่องเนทีฟ โดยทั่วไป เหตุใดจึงไม่มีภาษาใดที่สามารถประพฤติได้ทั้งภาษาที่แปลและตีความ


4
มีคือ Haskell ยังสามารถทำหน้าที่รวบรวมหรือตีความผ่าน GHCI
toasted_flakes

C ++ ยังมีล่าม และอาจมีภาษาอื่น ๆ อีกมากมายที่มีการใช้งาน
Claudio

2
จริงโดยการเลือก IronPythong ( ironpython.net ) และรวบรวมรหัส IL ผลิตโดยการใช้ "Ngen" ( msdn.microsoft.com/de-de/library/6t9t5wcf%28v=vs.110%29.aspx ) มีเป็นทาง เพื่อรวบรวม Python กับรหัสเครื่องเนทีฟ ไม่ใช่ว่าฉันได้ทดสอบเครื่องมือโซ่นั้น
Doc Brown

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

คำตอบ:


29

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

ในการรวบรวมภาษาอย่างมีประสิทธิภาพเช่น Python คุณจะต้อง:

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

6
เป็นที่น่าสังเกตว่าการทำเช่นนี้จะทำให้เกิดปัญหายากแต่ก็เป็นไปไม่ได้ sbclรวบรวม Common LISP ซึ่งเป็นแบบไดนามิกมีevalและสิ่งอื่น ๆ ที่จะทำให้นักเขียนคอมไพเลอร์เศร้า ไม่ใช่ระดับ gcc แต่แน่นอนว่าเร็วกว่าล่าม CPython
Daniel Gratzer

3
@jozefg ฉันบอกว่ารวบรวมได้อย่างมีประสิทธิภาพ ไม่เพียงแค่รวบรวม Python ก็มี Cython compiler ซึ่งสร้างรหัสดั้งเดิม ประเด็นก็คือคอมไพเลอร์เหล่านั้นไม่สามารถทำได้แม้แต่ส่วนของการปรับให้เหมาะสมที่คอมไพเลอร์สำหรับภาษาที่พิมพ์แบบคงที่สามารถ และเมื่อคุณเปรียบเทียบประสิทธิภาพให้เปรียบเทียบกับคอมไพล์ C ++ และไม่ตีความ Python
ร่าเริง

2
จริง ๆ แล้วคุณจะประหลาดใจในสิ่งที่ sbcl สามารถทำได้ เกมมาตรฐานแสดงให้เห็นว่ามันทำงานได้เร็วเท่ากับ Java เกือบเร็วเท่ากับ GHC และภายใน 1x ถึง 10 เท่าของ C มันไม่ได้ช้าตามมาตรฐานใด ๆ ใช่ประเภทไดนามิกหยุดการคอมไพล์ในระดับหนึ่ง แต่ไม่มากเท่าที่คุณคิด
Daniel Gratzer

3
การเปรียบเทียบความเร็วของไพ ธ อนที่ถูกตีความกับไพ ธ อนที่รวบรวมนั้นน่าสนใจในตัวมันเอง หยุดพูดว่า "ใช้ C ++" บางทีคุณอาจมีรหัสเขียนไว้ใน Python บางทีรหัสอาจเขียนได้ง่ายกว่าในภาษาไพ ธ อน ใครสน. สิ่งที่ฉันสนใจคือความเร็ว 1.5x ขึ้นอยู่กับว่ามันคืออะไร ที่สามารถสร้างความแตกต่างอย่างมาก
Thomas Eding

3
กล่าวอีกนัยหนึ่งถ้าคุณต้องการคอมไพล์ให้เลือกภาษาอื่นที่ปรับให้เหมาะกับภาษานั้นเช่น C ++ หรือ Pascal
Please_Dont_Bully_Me_SO_Lords

0

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

ฉันควรเริ่มด้วยการบอกว่าฉันไม่ใช่ผู้เชี่ยวชาญของ Python และฉันมาที่ไซต์นี้โดยไม่ได้ตั้งใจ แต่ฉันชอบเว็บไซต์นี้

ดังกล่าวในการตอบสนองอื่นที่นี่คอมไพเลอร์ C ++ สามารถรู้มากเกี่ยวกับโปรแกรมและตัดสินใจเกี่ยวกับการดำเนินงานที่จะใช้สำหรับโครงสร้างข้อมูลที่เฉพาะเจาะจง เป็นตัวอย่างถ้าจำเป็นต้องเพิ่มตัวแปรจำนวนเต็มสองตัวเข้าด้วยกันคอมไพเลอร์รู้ว่าพวกมันเป็นจำนวนเต็มพื้นฐาน 32 บิตและสามารถเพิ่มเข้าด้วยกันด้วยคำสั่ง "ADD" ดังนั้นจึงรวบรวมคำสั่ง ADD เป็นรหัส มันถูกล็อคอยู่และไม่สามารถเปลี่ยนแปลงได้ในขณะที่โปรแกรมกำลังทำงาน นั่นคือการผูกพันก่อน

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


-4

ฉันคิดว่ามันเกี่ยวข้องกับ Python เฉพาะเจาะจงมากกว่านั้นด้วยเหตุผลเดียวกันกับที่คุณไม่สามารถคอมไพล์รหัส C # กับรหัสเครื่องได้ เฉพาะภาษาจะทำให้โปรแกรมของคุณมีข้อผิดพลาดแม้ว่าจะเป็นไปได้เนื่องจากลักษณะของภาษา ทำไมไม่เพียงแค่เรียนรู้ภาษา C? มันง่ายกว่า C ++ และก้าวหน้ากว่า Python เล็กน้อย แต่ก็ยังเข้าถึงได้


5
C # สามารถไปที่รหัสเครื่องได้โดยตรง: Common Intermediate Language: Ahead of Time compilation - "สภาพแวดล้อมในการดำเนินการที่เข้ากันได้กับ CLI ยังมาพร้อมกับตัวเลือกในการรวบรวม Ahead-of-time compilation (AOT) ของแอสเซมบลี กระบวนการ JIT ที่รันไทม์ใน. NET Framework มีเครื่องมือพิเศษที่เรียกว่า Native Image Generator (NGEN) ที่ทำงานด้วย AOT ใน Mono มีตัวเลือกให้ทำ AOT ด้วย "
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.