คอมไพเลอร์ JIT สำหรับ C, C ++ และไลค์


33

มีคอมไพเลอร์ทันเวลาหรือไม่สำหรับภาษาที่คอมไพล์เช่น C และ C ++ (ชื่อแรกที่นึกได้คือ Clang และ LLVM! แต่ฉันไม่คิดว่าพวกเขาจะสนับสนุน)

คำอธิบาย:

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

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

อย่างไรก็ตามฉันคิดว่ามันเป็นเรื่องที่ถกเถียงกันอยู่ว่าการรวบรวม JIT นั้นมีประโยชน์มากกว่าค่าใช้จ่ายของตัวเอง


1
ทรัพยากรนอกหัวข้อเว็บไซต์
DeadMG

1
ไม่แน่ใจว่ามันเหมาะกับคำถามหรือไม่ แต่สำหรับผู้ที่คาดหวังการใช้งานฉันพบว่าแพคเกจ Cxxที่เป็นประโยชน์ในภาษาจูเลียนั้นให้การโต้ตอบ C ++ ที่คล้ายกับที่อธิบายไว้ในคำตอบ @ PhilippClaßen
Antonello

ตอนนี้ GCC 9 มีคอมไพเลอร์ jit gcc.gnu.org/onlinedocs/jit/intro/index.html
3071643

คำตอบ:


33

[ดูประวัติการแก้ไขสำหรับคำตอบที่ต่างออกไปซึ่งตอนนี้ล้าสมัยไปแล้ว]

ใช่มีคอมไพเลอร์ JIT สองสามตัวสำหรับ C และ / หรือ C ++

ยึด (ตามที่คุณคาดเดาจากเกม) ขึ้นอยู่กับ Clang / LLVM มันทำหน้าที่เหมือนล่าม นั่นคือคุณให้รหัสต้นฉบับบางส่วนให้คำสั่งเพื่อให้ทำงานและรัน การเน้นที่นี่ส่วนใหญ่เกี่ยวกับความสะดวกสบายและการรวบรวมที่รวดเร็วไม่ใช่การเพิ่มประสิทธิภาพสูงสุด เช่นนี้ถึงแม้ว่าในทางเทคนิคจะมีคำตอบสำหรับคำถามนี้ แต่มันก็ไม่เหมาะกับเจตนาของ OP มากนัก

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

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

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


1
เหตุใด JIT จึงไม่บันทึกไฟล์เหมือนแคชเพื่อให้สามารถข้ามการเรียนรู้ทุกอย่างตั้งแต่เริ่มต้นได้
JohnMudd

3
@ JohnMudd: ฉันสงสัยว่าเหตุผลคือความปลอดภัย เช่นแก้ไขรหัสแคชจากนั้นในครั้งต่อไปที่ VM เริ่มทำงานจะเรียกใช้งานรหัสที่ฉันใส่ไว้แทนที่จะเขียนสิ่งนั้น
Jerry Coffin

4
OTOH ถ้าคุณสามารถแก้ไขแคชคุณสามารถแก้ไขไฟล์ต้นฉบับได้
user3125367

1
@ user3125367: ใช่ แต่ในหลายกรณีคอมไพเลอร์ทำการตรวจสอบประเภทต่าง ๆ และสิ่งนั้นอาจถูกข้ามถ้าคุณโหลดโค้ดที่คอมไพล์โดยตรงจากแคช ขึ้นอยู่กับ JIT แน่นอน - Java มีการบังคับใช้งานจำนวนมากเมื่อโหลดไฟล์. class. (เรียบเรียง) แต่คนอื่น ๆ ส่วนใหญ่ทำน้อยกว่ามาก
Jerry Coffin

11

ใช่มีคอมไพเลอร์ JIT สำหรับ C ++ จากมุมมองประสิทธิภาพบริสุทธิ์ฉันคิดว่า Profile Guided Optimization (PGO) ยังคงเหนือกว่า

อย่างไรก็ตามนั่นไม่ได้หมายความว่าการรวบรวม JIT ยังไม่ได้ใช้ในทางปฏิบัติ ตัวอย่างเช่น Apple ใช้ LLVM เป็น JIT สำหรับไปป์ไลน์ OpenGL นั่นคือโดเมนที่คุณมีข้อมูลมากขึ้นตอนรันไทม์ซึ่งสามารถใช้เพื่อลบรหัสที่ตายแล้วจำนวนมาก

แอปพลิเคชั่นที่น่าสนใจอีกอย่างของ JIT คือ Cling ล่าม C ++ แบบโต้ตอบตาม LLVM และ Clang: https://root.cern.ch/cling

นี่คือตัวอย่างเซสชั่น:

[cling]$ #include <iostream>
[cling]$ std::cout << "Hallo, world!" << std::endl;
Hallo, world!
[cling]$ 3 + 5
(int const) 8
[cling]$ int x = 3; x++
(int) 3
(int const) 3
[cling]$ x
(int) 4

มันไม่ใช่โครงการของเล่น แต่มันถูกใช้จริงใน CERN ตัวอย่างเช่นเพื่อพัฒนารหัสสำหรับ Large Hadron Collider


7

C ++ / CLI ถูก jitted ได้รับแล้ว C ++ / CLI ไม่ใช่ C ++ แต่ใกล้เคียงกันแล้ว ที่กล่าวว่า JIT ของ Microsoft ไม่ได้ทำการปรับแต่งตามพฤติกรรมของรันไทม์ที่ชาญฉลาด / น่ารักอย่างที่คุณต้องการ ดังนั้นสิ่งนี้จึงไม่ช่วย

http://nestedvm.ibex.org/เปลี่ยน MIPS เป็น Java bytecode ซึ่งจะถูก jitted ปัญหาเกี่ยวกับวิธีการนี้จากคำถามของคุณคือคุณทิ้งข้อมูลที่มีประโยชน์มากมายในเวลาที่มันมาถึง JIT


2

ประการแรกฉันคิดว่าคุณต้องการติดตาม jit มากกว่าวิธี jit

วิธีที่ดีที่สุดที่จะใช้คือการรวบรวมรหัสไปยัง llvm IR จากนั้นเพิ่มรหัสการติดตามก่อนที่จะสร้างไฟล์ปฏิบัติการแบบเนทีฟ เมื่อบล็อคโค้ดมีการใช้งานที่ดีและเพียงพอเมื่อมีข้อมูลเกี่ยวกับค่า (ไม่ใช่ประเภทเช่นในภาษาไดนามิก) ของตัวแปรจะถูกรวบรวมดังนั้นโค้ดสามารถคอมไพล์ใหม่ได้ (จาก IR) พร้อมกับ guards ตามค่าของตัวแปร

ฉันดูเหมือนจะจำได้ว่ามีความคืบหน้าในการทำ ac / c ++ jit ใน clang ภายใต้ชื่อ libclang


1
AFAIK, libclang เป็นฟังก์ชั่นเสียงดังกราวส่วนใหญ่เอามาใช้เป็นห้องสมุด ดังนั้นคุณสามารถใช้มันเพื่อวิเคราะห์ซอร์สโค้ดเพื่อสร้างการระบายสีไวยากรณ์ที่ซับซ้อน, lints, การเรียกดูโค้ด ฯลฯ
Javier

@Javier ฟังดูแล้วน่ากังวล ฉันคิดว่ามีฟังก์ชั่นในห้องสมุดที่ใช้ const char * ของซอร์สโค้ดและสร้าง llvm ir แต่คิดว่าตอนนี้คงดีกว่า jit ที่อ้างอิงจาก ir แทนที่จะเป็นแหล่งที่มา
dan_waterworth
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.