โครงการซอฟต์แวร์ขนาดใหญ่มักจะประกอบด้วยหน่วยการรวบรวมจำนวนมากที่สามารถคอมไพล์ได้ค่อนข้างอิสระและการคอมไพล์มักจะขนานกันในระดับที่หยาบมากโดยการเรียกคอมไพเลอร์หลายครั้งพร้อมกัน สิ่งนี้เกิดขึ้นในระดับกระบวนการของ OS และประสานงานโดยระบบบิลด์แทนที่จะคอมไพเลอร์ที่เหมาะสม ฉันรู้ว่านี่ไม่ใช่สิ่งที่คุณถาม แต่นั่นเป็นสิ่งที่ใกล้เคียงกับการทำขนานในคอมไพเลอร์ส่วนใหญ่
ทำไมถึงเป็นอย่างนั้น? งานส่วนใหญ่ที่คอมไพเลอร์ไม่ได้ให้ตัวเองขนานกันอย่างง่ายดาย:
- คุณไม่สามารถแยกอินพุตให้เป็นชิ้น ๆ หลาย ๆ อันและแยกพวกมันออกเป็นอิสระ สำหรับความเรียบง่ายคุณต้องการแยกขอบเขต lexme (เพื่อไม่ให้เธรดเริ่มทำงานในช่วงกลางของ lexme) แต่การกำหนดขอบเขต lexme อาจต้องใช้บริบทจำนวนมาก ตัวอย่างเช่นเมื่อคุณข้ามไปที่กลางไฟล์คุณต้องตรวจสอบให้แน่ใจว่าคุณไม่ได้กระโดดเป็นตัวอักษรสตริง แต่เพื่อตรวจสอบเรื่องนี้คุณต้องดูโดยทั่วไปว่าตัวละครทุกตัวที่มาก่อนซึ่งเกือบจะใช้งานได้มากเท่ากับเริ่มต้นด้วย นอกจากนี้ lexing มักจะเป็นคอขวดในคอมไพเลอร์สำหรับภาษาสมัยใหม่
- การแยกคำนั้นยิ่งยากที่จะทำให้ขนานกัน ปัญหาทั้งหมดของการแยกข้อความที่ป้อนสำหรับ lexing ใช้มากขึ้นในการแยกโทเค็นสำหรับการแยก --- เช่นการกำหนดที่ฟังก์ชั่นเริ่มต้นเป็นเรื่องยากพอ ๆ กับการแยกเนื้อหาของฟังก์ชั่นที่จะเริ่มต้นด้วย ในขณะที่อาจมีวิธีการรอบ ๆ พวกเขาอาจจะซับซ้อนอย่างไม่เป็นสัดส่วนเพื่อประโยชน์เล็กน้อย การแยกวิเคราะห์ก็ไม่ได้เป็นคอขวดที่ใหญ่ที่สุด
- หลังจากที่คุณแยกวิเคราะห์แล้วคุณจะต้องทำการแก้ไขชื่อ แต่สิ่งนี้นำไปสู่ความสัมพันธ์ที่แน่นแฟ้น เมื่อต้องการแก้ไขวิธีการเรียกที่นี่คุณอาจจะต้องแก้ปัญหาการนำเข้าครั้งแรกในโมดูลนี้ แต่ผู้ที่จำเป็นต้องมีการแก้ไขชื่อในอีกรวบรวมหน่วย ฯลฯ เดียวกันสำหรับอนุมานชนิดถ้าภาษาของคุณมีว่า
หลังจากนี้มันจะง่ายขึ้นเล็กน้อย การตรวจสอบชนิดและการปรับให้เหมาะสมและการสร้างรหัสอาจโดยหลักการแล้วจะถูกขนานกันที่ฟังก์ชันย่อย ฉันยังรู้ไม่กี่ว่าคอมไพเลอร์ใดที่ทำสิ่งนี้อาจเป็นเพราะการทำงานขนาดใหญ่นี้พร้อมกันค่อนข้างท้าทาย คุณต้องพิจารณาด้วยว่าโครงการซอฟต์แวร์ขนาดใหญ่ส่วนใหญ่มีหน่วยการคอมไพล์จำนวนมากที่วิธี "รันคอมไพเลอร์หลายชุดพร้อมกัน" นั้นเพียงพอที่จะทำให้คอร์ทั้งหมดของคุณมีการใช้งาน (และในบางกรณีแม้แต่ฟาร์มเซิร์ฟเวอร์ทั้งหมด) นอกจากนี้ในงานรวบรวมขนาดใหญ่ดิสก์ I / O สามารถเป็นคอขวดได้มากเท่ากับการรวบรวมงานจริง
จากทั้งหมดที่กล่าวมาฉันรู้คอมไพเลอร์ที่ทำให้การสร้างโค้ดและการปรับให้เหมาะสมนั้นขนานกัน คอมไพเลอร์ Rust สามารถแยกงานแบ็คเอนด์ (LLVM ซึ่งรวมถึงการปรับแต่งโค้ดที่ใช้กันทั่วไปว่าเป็น "มิดเอนด์") ในหลาย ๆ เธรด สิ่งนี้เรียกว่า "หน่วยโค้ด - เจน" ตรงกันข้ามกับความเป็นไปได้ในการขนานอื่น ๆ ที่กล่าวถึงข้างต้นสิ่งนี้ประหยัดเนื่องจาก:
- ภาษามีหน่วยการคอมไพล์ค่อนข้างใหญ่ (เทียบกับพูด C หรือ Java) ดังนั้นอาจมีหน่วยการคอมไพล์ในการบินน้อยกว่าคุณมีแกน
- ส่วนที่ถูกขนานมักใช้เวลารวบรวมส่วนใหญ่
- ส่วนแบ็คเอนด์นั้นส่วนใหญ่แล้วจะขนานกันอย่างน่าละอาย - เพียงแค่ปรับให้เหมาะสมและแปลเป็นรหัสเครื่องแต่ละฟังก์ชั่นอย่างอิสระ แน่นอนว่าการเพิ่มประสิทธิภาพระหว่างโพรซีเดอร์และหน่วย codegen จะขัดขวางสิ่งเหล่านั้นและส่งผลกระทบต่อประสิทธิภาพการทำงาน แต่ไม่มีปัญหาทางความหมาย