ภาษาที่คอมไพเลอร์เขียนใน C จะเร็วกว่า C ได้อย่างไร?


175

ลองดูที่หน้าเว็บของ Juliaคุณสามารถดูเกณฑ์มาตรฐานของหลายภาษาในหลาย ๆ อัลกอริทึม (การกำหนดเวลาที่แสดงด้านล่าง) ภาษาที่คอมไพเลอร์เขียนด้วยภาษา C ได้ดีกว่าโค้ด C อย่างไร

ป้อนคำอธิบายรูปภาพที่นี่ รูป: เวลามาตรฐานเทียบกับ C (เล็กกว่าดีกว่า, ประสิทธิภาพ C = 1.0)


6
คำถามที่เกี่ยวข้องอย่างใกล้ชิด
Raphael

382
รถยนต์ซึ่งเป็นวัตถุที่มนุษย์สร้างขึ้นสามารถเคลื่อนที่ได้เร็วกว่ามนุษย์ได้อย่างไร
Babou

19
ตามตาราง Python ช้ากว่า C คุณคิดว่ามันเป็นไปไม่ได้ที่จะเขียนคอมไพเลอร์ C ใน Python ที่สร้างรหัสเดียวกันกับคอมไพเลอร์ C ที่คุณชื่นชอบ? แล้วภาษานั้นเขียนด้วยภาษาอะไร?
Carsten S

6
ความคิดเห็นของ babou เป็นแบบจุด แต่ฉันไม่คิดว่าเราต้องการแบบเดียวกันหลายรุ่น
ราฟาเอล

14
ความคิดที่เกี่ยวข้อง คอมไพเลอร์จำนวนมากเป็นโฮสติ้งของตัวเองซึ่งหมายความว่าพวกเขาเขียนด้วยภาษาของตัวเอง (มักจะรวมถึงการประกอบบางส่วน) และรวบรวมด้วยเวอร์ชั่นก่อนหน้าของตัวเอง แต่คอมไพเลอร์ก็ดีขึ้นเรื่อย ๆ พัดใจ
Schwern

คำตอบ:


263

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

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

เป็นตัวอย่างที่เป็นรูปธรรมมาดู Python ให้ละเอียดยิ่งขึ้น Python มีการนำไปใช้งานหลายอย่าง ที่พบมากที่สุดคือ CPython ซึ่งเป็นล่าม bytecode ที่เขียนใน C. นอกจากนี้ยังมี PyPy ซึ่งถูกเขียนในภาษาเฉพาะของ Python ที่เรียกว่า RPython และใช้รูปแบบการรวบรวมแบบผสมผสานเช่น JVM PyPy เร็วกว่า CPython ในเกณฑ์มาตรฐานส่วนใหญ่ มันใช้เทคนิคที่น่าทึ่งทุกประเภทเพื่อเพิ่มประสิทธิภาพของรหัสเมื่อรันไทม์ อย่างไรก็ตามภาษา Python ที่ PyPy รันนั้นเป็นภาษา Python เดียวกับที่ CPython รันซึ่งจะมีข้อแตกต่างเล็กน้อยซึ่งไม่มีผลต่อประสิทธิภาพ

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

จากการสแกนตารางมาตรฐานของเว็บไซต์ Julia ดูเหมือนว่าไม่มีภาษาใดที่ทำงานกับล่าม (Python, R, Matlab / Octave, Javascript) มีการวัดประสิทธิภาพที่พวกเขาเอาชนะ C ซึ่งโดยทั่วไปจะสอดคล้องกับสิ่งที่ฉันคาดหวังที่จะเห็น แม้ว่าฉันจะจินตนาการได้ว่าโค้ดที่เขียนด้วย Numpy library ที่ดีที่สุดของ Python (เขียนใน C และ Fortran) ก็คือการใช้งาน C ที่เป็นไปได้ของโค้ดที่คล้ายกัน ภาษาที่มีค่าเท่ากับหรือดีกว่า C กำลังรวบรวม (Fortran, Julia ) หรือใช้รูปแบบไฮบริดที่มีการคอมไพล์บางส่วน (Java และอาจ LuaJIT) PyPy ยังใช้โมเดลไฮบริดดังนั้นจึงเป็นไปได้อย่างสมบูรณ์ว่าถ้าเรารัน Python code เดียวกันบน PyPy แทนที่จะเป็น CPython เราจะเห็นว่ามันเอาชนะ C ในเกณฑ์มาตรฐานบางอย่าง


9
นี่คือคำตอบที่น่าอัศจรรย์ ชัดเจนเข้าใจและให้ข้อมูลมาก ขอบคุณมากที่สละเวลาเขียนมัน!
Alex A.

7
ทั้งจาวาสคริปต์และจาวากำลังทำงานกับคอมไพเลอร์ JIT แต่จาวามีหนึ่งการทดสอบที่เร็วขึ้นแล้วซีเหตุผลที่ใหญ่ที่สุดว่าทำไมรันไทม์ / คอมไพเลอร์สามารถทำงานได้เร็วขึ้นเนื่องจากมีข้อมูลเพิ่มเติมใช้ได้ คอมไพเลอร์ C / C ++ สามารถเพิ่มประสิทธิภาพโค้ด (ปกติ) มากขึ้นแล้วมีคนเขียนชุดประกอบด้วยมือเพียงเพราะคอมไพเลอร์มีข้อมูลเพิ่มเติมพร้อมใช้งาน แน่นอนว่าในทางทฤษฎีคนสามารถเขียนรหัสประกอบได้ดีขึ้น แต่ต้องมีความรู้และทักษะมากขึ้นดังนั้นคนส่วนใหญ่ก็มีภาษา JIT ที่สามารถขยายตัวได้มากขึ้นและสามารถปรับให้เหมาะสมสำหรับเครื่องจักรที่แน่นอนทำงานอยู่
Programmdude

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

@ hellquist แน่นอนว่าถ้ามาตรฐานนั้นเพียงพอและคอมไพเลอร์ฉลาดพอ แต่นั่นไม่ได้เกี่ยวข้องโดยตรงกับภาษาการใช้งานคอมไพเลอร์โดยตรงหรืออย่างตรงไปตรงมาดังนั้นฉันจึงไม่ได้พูดถึงที่นี่
tsleyson

97

เครื่องจักรที่มนุษย์สร้างขึ้นจะแข็งแกร่งกว่ามนุษย์ได้อย่างไร? นี่เป็นคำถามเดียวกันทั้งหมด

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


33
โปรแกรมหมากรุกสามารถเอาชนะมนุษย์ที่เขียนมันได้อย่างไร
Thorbjørn Ravn Andersen

25
ด้วยการเคลื่อนไหวที่ดีขึ้น! <rimshot>
Tony Ennis

ในการถอดความคำตอบของ Penn Gilette ว่าทำไมมันไม่สำคัญว่าคอมพิวเตอร์สามารถเอาชนะผู้ชายที่เล่นหมากรุก: "คุณคาดหวังว่าหุ่นยนต์ที่ออกแบบโดย GE จะแพ้ผู้ชายในการแข่งขันชกมวยหรือไม่?"
Dave Kanter

90

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

ไม่มีสิ่งใดในภาษาที่ช้าหรือเร็ว ¹

ในทางของเราไปยัง CPU ทำสิ่งจริง ๆ มีหลายขั้นตอน²

  1. โปรแกรมเมอร์อย่างน้อยหนึ่งคนที่มีชุดทักษะบางอย่าง
  2. ภาษา (เป็นทางการ) ที่โปรแกรมใช้ใน ("ซอร์สโค้ด")
  3. ห้องสมุดที่พวกเขาใช้
  4. สิ่งที่แปลซอร์สโค้ดเป็นรหัสเครื่อง (คอมไพเลอร์, ล่าม)
  5. สถาปัตยกรรมฮาร์ดแวร์โดยรวมเช่นจำนวนหน่วยการประมวลผลและโครงร่างของลำดับชั้นหน่วยความจำ
  6. ระบบปฏิบัติการที่จัดการกับฮาร์ดแวร์
  7. การเพิ่มประสิทธิภาพ On-CPU

ทุกรายการเดียวมีส่วนช่วยในรันไทม์จริงที่คุณสามารถวัดได้ "ภาษา" ที่แตกต่างกันมุ่งเน้นไปที่สิ่งต่าง ๆ ³

เพียงเพื่อให้ตัวอย่าง

  • 1 vs 2-4 : โปรแกรมเมอร์ C เฉลี่ยมีแนวโน้มที่จะสร้างโค้ดที่แย่กว่าโปรแกรมเมอร์ Java โดยเฉลี่ยทั้งในแง่ของความถูกต้องและประสิทธิภาพ นั่นเป็นเพราะโปรแกรมเมอร์มีความรับผิดชอบมากขึ้นในซี

  • 1/4 VS 7 : ในภาษาระดับต่ำเช่น C คุณอาจจะสามารถใช้ประโยชน์จากคุณสมบัติของ CPU บางอย่างเป็นโปรแกรมเมอร์ ในภาษาระดับสูงกว่าเฉพาะคอมไพเลอร์ / ล่ามเท่านั้นที่สามารถทำได้และเฉพาะเมื่อพวกเขารู้ CPU เป้าหมาย

  • 1/4 vs 5 : คุณต้องการหรือต้องควบคุมเลย์เอาต์ของหน่วยความจำเพื่อที่จะใช้สถาปัตยกรรมหน่วยความจำที่ดีที่สุดได้หรือไม่? บางภาษาให้คุณควบคุมสิ่งนั้นไม่ได้

  • 2/4 VS 3 : ตีความงูหลามตัวเองเป็นอย่างน่ากลัวช้า แต่มีการผูกที่นิยมอย่างมากในการเพิ่มประสิทธิภาพห้องสมุดรวบรวมกำเนิดสำหรับการคำนวณทางวิทยาศาสตร์ ดังนั้นการทำบางสิ่งใน Python จึงเป็นไปอย่างรวดเร็วในที่สุดหากงานส่วนใหญ่ทำโดยไลบรารีเหล่านี้

  • 2 vs 4 : ล่าม Ruby มาตรฐานค่อนข้างช้า ในทางตรงกันข้าม JRuby นั้นเร็วมาก นั่นเป็นภาษาเดียวกันที่รวดเร็วโดยใช้คอมไพเลอร์ / ล่ามอื่น

  • 1/2 vs 4 : การใช้การปรับให้เหมาะสมของคอมไพเลอร์สามารถแปลโค้ดง่าย ๆ เป็นรหัสเครื่องที่มีประสิทธิภาพมาก

บรรทัดล่างคือมาตรฐานที่คุณพบว่าไม่สมเหตุสมผลมากอย่างน้อยก็ไม่ได้เมื่อต้มลงในตารางที่คุณรวมไว้ แม้ว่าสิ่งที่คุณสนใจคือเวลาทำงานคุณต้องระบุทั้งห่วงโซ่จากโปรแกรมเมอร์เป็นซีพียู; การสลับองค์ประกอบใด ๆ สามารถเปลี่ยนผลลัพธ์ได้อย่างมาก

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


  1. มีแน่นอนมีคุณสมบัติภาษาที่มีค่าใช้จ่ายเพิ่มเติมในการดำเนินการกว่าคนอื่น ๆ แต่การมีอยู่ของฟีเจอร์ไม่ได้หมายความว่าคุณจะต้องใช้มันและฟีเจอร์ที่มีราคาแพงอาจช่วยประหยัดการใช้ฟีเจอร์ที่ราคาถูกกว่ามากมาย (มีข้อดีอื่น ๆ ที่ไม่สามารถวัดได้ในเวลาใช้งาน)
  2. ฉันข้ามระดับอัลกอริธึมเนื่องจากไม่ได้นำไปใช้เสมอและส่วนใหญ่ไม่ขึ้นอยู่กับภาษาการเขียนโปรแกรมที่ใช้ โปรดทราบว่าอัลกอริทึมที่แตกต่างให้ยืมตัวเองดีกว่ากับฮาร์ดแวร์ที่แตกต่างกันเช่น
  3. ฉันจงใจไม่ไปสู่ตัวชี้วัดความสำเร็จที่แตกต่างกันที่นี่: ประสิทธิภาพเวลาทำงานประสิทธิภาพหน่วยความจำเวลานักพัฒนาระบบความปลอดภัยความปลอดภัย (พิสูจน์ได้) ความถูกต้องการสนับสนุนเครื่องมือแพลตฟอร์มอิสระ ...

    การเปรียบเทียบภาษา wrt หนึ่งตัวชี้วัดถึงแม้ว่าพวกเขาได้รับการออกแบบมาเพื่อเป้าหมายที่แตกต่างกันโดยสิ้นเชิงเป็นความผิดพลาดอย่างใหญ่หลวง


1
@Babou ตกลงคำอธิบายที่ดีมาก ดังนั้นสิ่งที่จะเป็นตัวชี้วัดที่ดีกว่าหรือบางทีอาจเป็นชุดของตัวชี้วัดที่สามารถใช้ในการเปรียบเทียบภาษากับคอมไพเลอร์ / ล่ามที่เกี่ยวข้อง? นอกจากนี้ nitpick เล็กน้อย: คุณพูดว่า "ไม่มีสิ่งใดเป็นภาษาช้าหรือเร็ว" จากนั้น "Python เองช้ามาก" แต่ฉันคิดว่าคุณหมายถึงล่าม Python
StrugglingProgrammer

2
@benalbrecht จุดของฉันคือว่าไม่มีชุดดังกล่าวที่ดีเพียงชุดเดียว มันเป็นการแลกเปลี่ยนที่ดีเสมอ หากคุณสร้างไดรเวอร์อุปกรณ์คุณต้องการแก้ไขให้ถูกต้องเหนือสิ่งอื่นใด หากคุณสร้างกระดูกสันหลังของ Twitter คุณต้องการมีประสิทธิภาพเหนือสิ่งอื่นใด ในทั้งสองกรณีคุณใช้เครื่องมือและจ้างคนที่ได้รับอนุญาต หากคุณเป็นผู้เริ่มต้นใช้งานแอพพลิเคชั่น Android คุณจะใช้สิ่งที่คนของคุณรู้จักและ / หรือลดเวลาในการออกสู่ตลาด หากคุณสอนอัลกอริทึมคุณต้องการภาษาที่มีไวยากรณ์ที่กระชับชัดเจนและสำเร็จรูปขนาดเล็ก และอื่น ๆ ลำดับความสำคัญแตกต่างกันดังนั้นเราจึงมีภาษาที่แตกต่างกัน
Raphael

ดูคำถามที่เกี่ยวข้องกันนี้โดยละเอียด
Raphael

23

มีสิ่งหนึ่งที่ลืมเกี่ยวกับการเพิ่มประสิทธิภาพที่นี่

มีการถกเถียงกันอย่างยาวนานเกี่ยวกับ Fortran ที่มีประสิทธิภาพสูงกว่า C. การแยกการอภิปรายที่ผิดรูปแบบ: รหัสเดียวกันถูกเขียนใน C และ Fortran (ตามที่ผู้ทดสอบคิด) และการทดสอบประสิทธิภาพตามข้อมูลเดียวกัน ปัญหาคือภาษาเหล่านี้แตกต่างกัน C อนุญาตให้ใช้นามแฝงของพอยน์เตอร์ในขณะที่ Fortran ไม่ได้

ดังนั้นรหัสจึงไม่เหมือนกันจึงไม่มี __ จำกัด ในไฟล์ทดสอบ C ซึ่งให้ความแตกต่างหลังจากเขียนไฟล์ใหม่เพื่อบอกคอมไพเลอร์ว่าสามารถเพิ่มประสิทธิภาพพอยน์เตอร์ได้

จุดนี่คือเทคนิคการเพิ่มประสิทธิภาพบางอย่างง่ายขึ้น (หรือเริ่มถูกกฎหมาย) ในภาษาที่สร้างขึ้นใหม่

นอกจากนี้ยังเป็นไปได้ในระยะยาวกับ VM ด้วย JIT ประสิทธิภาพที่เหนือกว่า C. มีความเป็นไปได้สองประการ:
รหัส JIT สามารถใช้ประโยชน์จากเครื่องที่โฮสต์ (ตัวอย่างเช่น SSEหรือSSEพิเศษบางอย่างสำหรับคำแนะนำเวกเตอร์ซีพียูบางตัว) โปรแกรมเปรียบเทียบX

ประการที่สอง VM สามารถทำการทดสอบแรงดันในขณะที่ทำงานเพื่อให้สามารถรับรหัสที่มีความกดดันและปรับให้เหมาะสมหรือแม้แต่คำนวณล่วงหน้าในระหว่างรันไทม์ โปรแกรม C ที่คอมไพล์ล่วงหน้าไม่คาดหวังว่าแรงกดดันหรือ (ส่วนใหญ่) มีเวอร์ชันทั่วไปของไฟล์ประมวลผลสำหรับตระกูลทั่วไปของเครื่อง

ในการทดสอบนี้มี JS ด้วย, มี VMs เร็วกว่า V8 และยังทำงานได้เร็วกว่า C ในการทดสอบบางอย่าง

ฉันตรวจสอบแล้วและมีเทคนิคการเพิ่มประสิทธิภาพที่ไม่เหมือนใครซึ่งยังไม่มีในคอมไพเลอร์ C

คอมไพเลอร์ C จะต้องทำการวิเคราะห์แบบคงที่ของรหัสทั้งหมดในครั้งเดียวเดินขบวนตามแพลตฟอร์มที่กำหนดและแก้ไขปัญหาการจัดตำแหน่งหน่วยความจำ

VM เพิ่งทับศัพท์ส่วนหนึ่งของรหัสเพื่อเพิ่มประสิทธิภาพการประกอบและเรียกใช้

เกี่ยวกับ Julia - เมื่อฉันตรวจสอบว่ามันทำงานกับ AST ของรหัสเช่น GCC ข้ามขั้นตอนนี้เพิ่งจะเริ่มใช้ข้อมูลจากที่นั่น รวมถึงข้อ จำกัด อื่น ๆ และเทคนิค VM อาจอธิบายเล็กน้อย

ตัวอย่าง: ให้เราใช้ลูปอย่างง่ายที่จะเริ่มจุดสิ้นสุดจุดสิ้นสุดจากตัวแปรและโหลดส่วนหนึ่งของตัวแปรในการคำนวณรู้ที่รันไทม์

คอมไพเลอร์ C สร้างตัวแปรโหลดจากการลงทะเบียน
แต่ ณ รันไทม์ตัวแปรเหล่านี้รู้จักและถือว่าเป็นค่าคงที่ผ่านการดำเนินการ
ดังนั้นแทนที่จะโหลดตัวแปรจากรีจิสเตอร์ (และไม่ทำการแคชเนื่องจากมันสามารถเปลี่ยนแปลงได้และจากการวิเคราะห์แบบสแตติกมันไม่ชัดเจน) พวกมันจะได้รับการปฏิบัติอย่างเต็มที่เช่นค่าคงที่และการพับ, การแพร่กระจาย


12

คำตอบก่อนหน้าให้สวยมากคำอธิบาย แต่ส่วนใหญ่มาจากมุมมองในทางปฏิบัติให้มากที่สุดเท่าคำถามที่ทำให้รู้สึกตามที่อธิบายไว้อย่างดีโดยคำตอบของราฟาเอล

ในการเพิ่มคำตอบนี้เราควรทราบว่าในปัจจุบันคอมไพเลอร์ C เขียนเป็น C แน่นอนตามที่ระบุโดย Raphael เอาต์พุตและประสิทธิภาพอาจขึ้นอยู่กับสิ่งอื่น ๆ บน CPU ที่ทำงานอยู่ แต่ก็ยังขึ้นอยู่กับปริมาณของการปรับให้เหมาะสมที่คอมไพเลอร์ทำ หากคุณเขียนคอมไพเลอร์ที่ปรับค่าให้เหมาะสมให้ดีขึ้นสำหรับ C (ซึ่งคุณจะคอมไพล์กับอันเก่าเพื่อให้สามารถรันได้) คุณจะได้คอมไพเลอร์ตัวใหม่ที่ทำให้ C เป็นภาษาที่เร็วกว่าเดิม แล้วความเร็วของ C คืออะไร? โปรดทราบว่าคุณสามารถรวบรวมคอมไพเลอร์ใหม่ด้วยตัวเองในฐานะการส่งครั้งที่สองเพื่อให้สามารถรวบรวมได้อย่างมีประสิทธิภาพมากขึ้นแม้ว่าจะยังคงให้รหัสวัตถุเดียวกัน และทฤษฎีการจ้างงานเต็มรูปแบบแสดงให้เห็นว่าพวกเขาไม่มีจุดจบในการปรับปรุงดังกล่าว (ขอบคุณราฟาเอลสำหรับตัวชี้)

แต่ฉันคิดว่ามันอาจจะคุ้มค่าที่จะพยายามทำให้เป็นทางการปัญหาเพราะมันแสดงให้เห็นถึงแนวคิดพื้นฐานบางอย่างที่ดีมากและโดยเฉพาะอย่างยิ่ง denotational กับมุมมองการดำเนินงาน

คอมไพเลอร์คืออะไร?

CSTCCSTP:SP SP:T TP

CSTCST{(P:S,P:T)PSSPTT}

CSTPSPTP

P:TP:SCST

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

เกี่ยวกับ bootstrapping

สิ่งนี้จะแสดงให้เห็นถึงความแตกต่างและแสดงการใช้งานจริง

SISCST:SSCST:SISP:SP:TST

CST:SSCST:TTTT


"สิ่งที่สำคัญในเชิงความหมายคือสิ่งที่ทำไม่ใช่วิธีการ (และรวดเร็ว) ในการทำ" - มันกล่าวถึงเกณฑ์ที่ไม่สามารถใช้งานได้จริงในทางปฏิบัติ มีโปรแกรมเป้าหมายที่เทียบเท่ากับการใช้งานหลายอย่าง แต่เราอาจชอบมากกว่าโปรแกรมอื่น ๆ ด้วยเหตุผลบางอย่าง (ประสิทธิภาพ, ขนาด, การจัดตำแหน่งหน่วยความจำที่ดีกว่า, ... ) กล่าวคือมุมมองของคอมไพเลอร์เป็นฟังก์ชั่นตามที่คุณกำหนดนั้นมี จำกัด มากกว่าที่เราต้องการ มันให้บริการเพื่อวัตถุประสงค์ที่คุณต้องการอธิบาย
ราฟาเอล

@ ราฟาเอลเกี่ยวกับทฤษฎีการจ้างงานเต็มรูปแบบฉันมีความคิด (ในความคิดเห็นของฉันใน C) แต่ฉันไม่ทราบชื่อและเลื่อนการค้นหาการอ้างอิง ขอบคุณที่ทำ --- ความหมายที่ฉันพูดถึงคือคอมไพเลอร์ไม่ใช่ของโปรแกรมเป้าหมาย โปรแกรมเป้าหมายจะได้รับการเก็บรักษาไว้ในทาง syntactically และการดำเนินการไม่เพียง แต่ความหมาย หรือฉันเข้าใจผิดคำพูดของคุณ ฉันแก้ไขเพื่อทำให้สิ่งต่าง ๆ มีความแม่นยำมากขึ้นในข้อความของฉัน
babou

@Raphael เนื่องจากคุณไม่ได้ลบความคิดเห็นของคุณหมายความว่าฉันเข้าใจผิดหรือไม่ตอบถูกหรือไม่ มันเป็นอย่างไรที่มุมมองของคอมไพเลอร์ (ไม่ใช่ของโปรแกรมรวบรวม) เป็นฟังก์ชั่น จำกัด เกินไปจากมุมมองความหมายของความหมาย แน่นอนว่าเป็นฟังก์ชั่นอาจใช้อาร์กิวเมนต์อื่นนอกเหนือจากโปรแกรมที่คอมไพล์เช่นคำสั่งการปรับให้เหมาะสม) แต่นี่เป็นรายละเอียดที่จะไม่เปลี่ยนการสนทนา
Babou

ฉันคิดว่าความคิดเห็นของฉันเป็นตัวชี้ไปยัง "มีมากกว่าแบบนี้" สิ่งที่คุณเขียนไม่ผิด แต่ไม่ใช่ทุกอย่าง ในทางทฤษฎีนี้ดูเหมือนชัดเจน "ว่า" ฟังก์ชั่นคอมไพเลอร์ไม่ได้ต่อ se ที่ดีที่กำหนดเนื่องจากมีอยู่มากมายหลายโปรแกรมเป้าหมายที่เป็นไปได้ทั้งหมดเทียบเท่าความหมาย สิ่งที่ควรเลือกเป็นส่วนสำคัญในการออกแบบคอมไพเลอร์
Raphael

CP

6

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

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


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

ฉันเดาว่าขึ้นอยู่กับว่าคุณตีความคำว่า "แอปพลิเคชั่นเฉพาะประเภท" ในวงกว้างอย่างไร แม้ว่าจะเป็นความจริงที่ว่าภาษากระแสหลักส่วนใหญ่ไม่ใช่ DSL แต่ก็แน่นอนว่าได้รับการออกแบบโดยคำนึงถึงการใช้งานบางอย่าง C ถูกออกแบบมาเพื่อใช้ Unix Java ได้รับการออกแบบสำหรับสคริปต์ทีวีแบบอินเทอร์แอคทีฟ Smalltalk ถูกออกแบบมาสำหรับการสอนเด็ก ECMAScript ได้รับการออกแบบสำหรับการเขียนสคริปต์บนเว็บเซิร์ฟเวอร์และฝั่งไคลเอ็นต์ Perl ถูกออกแบบมาสำหรับการประมวลผลข้อความและการเขียนสคริปต์ Unix PHP ได้รับการออกแบบสำหรับการเขียนสคริปต์เว็บเซิร์ฟเวอร์ Erlang ถูกออกแบบมาเพื่อความน่าเชื่อถือ โครงการถูกออกแบบมาสำหรับการสำรวจ ...
Jörg W Mittag

…รากฐานของ OO และโมเดลนักแสดง APL ได้รับการออกแบบเป็นสัญลักษณ์สำหรับการสอนคณิตศาสตร์ Julia ถูกออกแบบมาสำหรับการเขียนโปรแกรมทางวิทยาศาสตร์ แน่นอนว่าภาษาเหล่านั้นทั้งหมดถูกใช้นอกโดเมนปัญหาดั้งเดิมของพวกเขา แต่ยังมีคุณสมบัติบางอย่างในภาษาเหล่านั้นที่ทำให้พวกเขาดีขึ้นหรือแย่ลงสำหรับแอพพลิเคชั่นบางประเภทแม้ว่าพวกเขาจะสามารถใช้สร้างทุกประเภทได้ สิ่ง
Jörg W Mittag

4

กลับไปที่บรรทัดเดิม: "ภาษาที่คอมไพเลอร์เขียนด้วย C จะเร็วกว่า C ได้อย่างไร" ฉันคิดว่านี่น่าจะหมายถึงว่าโปรแกรมที่เขียนใน Julia ซึ่งเป็นแกนกลางที่เขียนด้วย C จะเร็วกว่าโปรแกรมที่เขียนใน C ได้อย่างไร โดยเฉพาะโปรแกรม "mandel" ตามที่เขียนใน Julia ทำงานใน 87% ของเวลาดำเนินการของโปรแกรม "mandel" ที่เทียบเท่ากันที่เขียนใน C อย่างไร

บทความของ Babou เป็นคำตอบเดียวที่ถูกต้องสำหรับคำถามนี้ การตอบกลับอื่น ๆ ทั้งหมดนั้นเป็นการตอบคำถามอื่น ๆ ไม่มากก็น้อย ปัญหาเกี่ยวกับข้อความของ babou คือคำอธิบายทางทฤษฎีที่ยาวหลายย่อหน้าของ "What is a compiler" ถูกเขียนในแง่ที่ว่าโปสเตอร์ต้นฉบับอาจจะมีปัญหาในการทำความเข้าใจ ใครก็ตามที่เข้าใจแนวคิดที่อ้างอิงโดยคำว่า "semantic", "denotonom", "realization", "computing" และอื่น ๆ จะรู้คำตอบของคำถามอยู่แล้ว

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

เราสามารถจินตนาการได้ว่าภาษาการเขียนโปรแกรมที่มีทั้งตัวดำเนินการ "บวก" และ "ทวีคูณ" และอีกภาษาหนึ่งที่มี "บวก" เท่านั้น หากการคำนวณของคุณต้องการการคูณภาษาหนึ่งจะ "ช้าลง" เพราะแน่นอนว่า CPU สามารถทำทั้งสองอย่างโดยตรง แต่ถ้าคุณไม่มีวิธีใดที่จะแสดงความจำเป็นในการคูณ 5 * 5 คุณจะต้องเขียน "5 + 5 + 5 + 5 + 5 " หลังจะใช้เวลามากขึ้นในการมาถึงคำตอบเดียวกัน สันนิษฐานว่ามีบางอย่างเกิดขึ้นกับจูเลีย บางทีภาษาช่วยให้โปรแกรมเมอร์ระบุเป้าหมายที่ต้องการในการคำนวณชุด Mandelbrot ในลักษณะที่ไม่สามารถแสดงได้โดยตรงใน C

โปรเซสเซอร์ที่ใช้เป็นเกณฑ์มาตรฐานถูกระบุว่าเป็นซีพียู Xeon E7-8850 2.00GHz เกณฑ์มาตรฐาน C ใช้คอมไพเลอร์ gcc 4.8.2 เพื่อสร้างคำสั่งสำหรับ CPU นั้นในขณะที่ Julia ใช้เฟรมเวิร์กคอมไพเลอร์ LLVM เป็นไปได้ว่าแบ็กเอนด์ของ gcc (ส่วนที่สร้างรหัสเครื่องสำหรับสถาปัตยกรรม CPU เฉพาะ) ไม่ได้เป็นขั้นสูงในทางใดทางหนึ่งเป็นแบ็กเอนด์ LLVM นั่นอาจสร้างความแตกต่างในประสิทธิภาพ นอกจากนี้ยังมีอีกหลายสิ่งที่เกิดขึ้น - คอมไพเลอร์สามารถ "ปรับ" โดยอาจออกคำสั่งในลำดับที่แตกต่างจากที่ระบุโดยโปรแกรมเมอร์หรือแม้กระทั่งไม่ทำอะไรเลยถ้ามันสามารถวิเคราะห์รหัสและตรวจสอบว่าพวกเขาไม่ จำเป็นต้องได้รับคำตอบที่ถูกต้อง และโปรแกรมเมอร์อาจเขียนส่วนหนึ่งของโปรแกรม C ด้วยวิธีที่ทำให้มันช้า แต่ก็ไม่ได้ '

ทั้งหมดนี้เป็นวิธีการพูด: มีหลายวิธีในการเขียนรหัสเครื่องเพื่อคำนวณชุด Mandelbrot และภาษาที่คุณใช้มีผลกระทบอย่างมากต่อวิธีการเขียนรหัสเครื่อง ยิ่งคุณมีความเข้าใจเกี่ยวกับการรวบรวมชุดคำสั่งแคชและอื่น ๆ มากเท่าไหร่คุณก็ยิ่งมีความพร้อมมากขึ้นเท่านั้นที่จะได้รับผลลัพธ์ที่คุณต้องการ ประเด็นสำคัญจากผลการทดสอบเกณฑ์มาตรฐานที่ระบุไว้สำหรับ Julia คือไม่มีภาษาหรือเครื่องมือใดที่ดีที่สุดในทุกสิ่ง ในความเป็นจริงปัจจัยด้านความเร็วที่ดีที่สุดในกราฟทั้งหมดสำหรับ Java!


2

ความเร็วของโปรแกรมที่คอมไพล์ขึ้นอยู่กับสองสิ่ง:

  1. ลักษณะการทำงานของเครื่องที่กำลังดำเนินการอยู่
  2. เนื้อหาของไฟล์เรียกทำงาน

ภาษาที่คอมไพเลอร์เขียนนั้นไม่เกี่ยวข้องกับ (1) ตัวอย่างเช่นคอมไพเลอร์ Java สามารถเขียนใน C หรือ Java หรือ Python แต่ในทุกกรณี "เครื่องจักร" ที่รันโปรแกรมคือ JVM

ภาษาที่คอมไพเลอร์เขียนนั้นไม่เกี่ยวข้องกับ (2) ตัวอย่างเช่นไม่มีเหตุผลว่าทำไมคอมไพเลอร์ C ที่เขียนใน Python ไม่สามารถส่งออกไฟล์ที่สามารถใช้งานได้เหมือนกับไฟล์คอมไพเลอร์ C ที่เขียนใน C หรือ Java


1

ฉันจะพยายามเสนอคำตอบสั้น ๆ

หลักของคำถามที่อยู่ในคำนิยามของ "ความเร็ว" ของภาษา

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

* ข้อสันนิษฐานผิดพลาดเป็นครั้งคราว


0

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

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


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