ฉันสงสัยอยู่เสมอว่าทำไมโปรเซสเซอร์หยุดทำงานที่การลงทะเบียน 32 ครั้ง มันเป็นชิ้นส่วนที่เร็วที่สุดของเครื่องทำไมไม่เพียงสร้างตัวประมวลผลที่ใหญ่กว่าด้วยการลงทะเบียนมากขึ้น? นั่นจะหมายถึงการไปที่ RAM น้อยลงหรือไม่
ฉันสงสัยอยู่เสมอว่าทำไมโปรเซสเซอร์หยุดทำงานที่การลงทะเบียน 32 ครั้ง มันเป็นชิ้นส่วนที่เร็วที่สุดของเครื่องทำไมไม่เพียงสร้างตัวประมวลผลที่ใหญ่กว่าด้วยการลงทะเบียนมากขึ้น? นั่นจะหมายถึงการไปที่ RAM น้อยลงหรือไม่
คำตอบ:
ประการแรกสถาปัตยกรรมโปรเซสเซอร์ไม่ได้หยุดที่ 32 register สถาปัตยกรรม RISC เกือบทั้งหมดที่มีการลงทะเบียน 32 ชุดที่ปรากฏในชุดคำสั่งนั้นมีการลงทะเบียนจำนวนเต็ม 32 ตัวและการลงทะเบียนจุดลอยตัวอีก 32 จุด (เช่น 64) (จุดลอยตัว "เพิ่ม" ใช้การลงทะเบียนที่แตกต่างจากจำนวนเต็ม "เพิ่ม") สถาปัตยกรรม SPARC มีหน้าต่างการลงทะเบียน. ใน SPARC คุณสามารถเข้าถึงการลงทะเบียนจำนวนเต็ม 32 ครั้งเท่านั้น แต่การลงทะเบียนจะทำหน้าที่เหมือนสแต็กและคุณสามารถกดและรีจิสเตอร์ใหม่ 16 ครั้ง สถาปัตยกรรม Itanium จาก HP / Intel มีจำนวนเต็ม 128 จำนวนเต็มและมีการลงทะเบียนจุดลอยตัว 128 ตัวในชุดคำสั่ง GPU สมัยใหม่จาก NVidia, AMD, Intel, ARM และ Imagination Technologies ล้วนแล้วแต่มีการลงทะเบียนจำนวนมากในไฟล์ลงทะเบียน (ฉันรู้ว่านี่เป็นจริงของสถาปัตยกรรม NVidia และ Intel ฉันไม่คุ้นเคยกับชุดคำสั่ง AMD, ARM และ Imagination แต่ฉันคิดว่าไฟล์ลงทะเบียนมีขนาดใหญ่เช่นกัน)
ประการที่สองไมโครโปรเซสเซอร์ที่ทันสมัยส่วนใหญ่ใช้การเปลี่ยนชื่อรีจิสเตอร์เพื่อกำจัดอนุกรมที่ไม่จำเป็นซึ่งเกิดจากการจำเป็นต้องใช้ทรัพยากรซ้ำดังนั้นไฟล์ลงทะเบียนฟิสิคัลพื้นฐานอาจใหญ่กว่า (96, 128 หรือ 192 รีจิสเตอร์ในบางเครื่อง) ต้องการคอมไพเลอร์เพื่อสร้างชื่อรีจิสเตอร์ที่ไม่ซ้ำกันจำนวนมากในขณะที่ยังคงให้ไฟล์รีจิสเตอร์ขนาดใหญ่ลงในตัวกำหนดตารางเวลา
มีเหตุผลสองประการที่ทำให้เพิ่มจำนวนการลงทะเบียนในชุดคำสั่งได้ยากขึ้น ก่อนอื่นคุณจะต้องสามารถระบุตัวระบุการลงทะเบียนในแต่ละคำสั่ง 32 register ต้องการตัวระบุรีจิสเตอร์ 5 บิตดังนั้นคำแนะนำ 3-address (โดยทั่วไปบนสถาปัตยกรรม RISC) ใช้จ่าย 15 จาก 32 บิตคำสั่งเพื่อระบุรีจิสเตอร์ หากคุณเพิ่มขึ้นเป็น 6 หรือ 7 บิตคุณจะมีพื้นที่น้อยลงในการระบุรหัสและค่าคงที่ GPUs และ Itanium มีมากคำแนะนำที่มีขนาดใหญ่ คำแนะนำขนาดใหญ่มาพร้อมกับค่าใช้จ่าย: คุณต้องใช้หน่วยความจำคำสั่งเพิ่มเติมดังนั้นพฤติกรรมแคชคำสั่งของคุณจึงไม่เหมาะอย่างยิ่ง
เหตุผลที่สองคือเวลาเข้าถึง ยิ่งคุณสร้างหน่วยความจำมากเท่าไหร่ก็จะยิ่งเข้าถึงหน่วยความจำได้ช้าลงเท่านั้น (ในแง่ของฟิสิกส์พื้นฐาน: ข้อมูลถูกเก็บไว้ในพื้นที่ 2 มิติดังนั้นหากคุณเก็บบิตระยะทางเฉลี่ยไปยังบิตที่เจาะจงคือ ) ไฟล์ลงทะเบียนเป็นเพียง หน่วยความจำแบบมัลติพอร์ตขนาดเล็กและหนึ่งในข้อ จำกัด ในการทำให้มีขนาดใหญ่ขึ้นคือในที่สุดคุณจะต้องเริ่มตอกบัตรเครื่องของคุณช้าลงเพื่อรองรับไฟล์รีจิสเตอร์ขนาดใหญ่ โดยปกติแล้วในแง่ของประสิทธิภาพโดยรวมนี่ถือว่าเป็นการสูญเสีย O ( √
อีกสองเหตุผลในการ จำกัด จำนวนการลงทะเบียน:
รหัสจำนวนมากมีการเข้าถึงหน่วยความจำมากมาย (30% เป็นตัวเลขทั่วไป) จากนั้นโดยทั่วไปประมาณ 2 / 3rds คือการเข้าถึงแบบอ่านและ 1 / 3rds เป็นสิทธิ์การเขียน สิ่งนี้ไม่ได้เกิดจากการหมดเรจิสเตอร์เท่าที่เข้าถึงอาเรย์การเข้าถึงตัวแปรสมาชิกของวัตถุเป็นต้น
HAS นี้จะต้องทำในหน่วยความจำ (หรือแคชข้อมูล) เนื่องจากวิธีการทำ C / C ++ (ทุกสิ่งที่คุณสามารถรับตัวชี้จะต้องมีที่อยู่ที่จะต้องเก็บไว้ในหน่วยความจำ) หากคอมไพเลอร์สามารถเดาได้ว่าคุณจะไม่เขียนถึงตัวแปรจำใจโดยใช้เทคนิคตัวชี้ทางอ้อมแบบบ้ามันจะใส่ไว้ในรีจิสเตอร์และมันใช้งานได้ดีกับตัวแปรฟังก์ชั่น แต่ไม่ใช่สำหรับคนทั่วไป ()) เพราะมันเป็นไปไม่ได้ที่จะคาดเดาว่ารัฐโลกจะเปลี่ยนแปลงอย่างไร
ด้วยเหตุนี้จึงไม่ใช่เรื่องธรรมดาที่คอมไพเลอร์จะสามารถทำอะไรกับการใช้งานทั่วไปมากกว่า 16 รายการต่อไป นี่คือเหตุผลที่สถาปนิกยอดนิยมทั้งหมดมีจำนวนมาก (ARM มี 16)
MIPS และ RISC อื่น ๆ มีแนวโน้มที่จะมี 32 เพราะมันไม่ยากมากที่จะมีการลงทะเบียนจำนวนมาก - ค่าใช้จ่ายต่ำพอดังนั้นจึงเป็นบิตของ "ทำไมไม่" มากกว่า 32 ส่วนใหญ่ไม่มีประโยชน์และมีข้อเสียของการทำให้ไฟล์การลงทะเบียนใช้งานได้นานขึ้น (แต่ละครั้งที่เพิ่มจำนวนการลงทะเบียนอาจเพิ่มมัลติเพล็กเซอร์หลายชั้นซึ่งเพิ่มความล่าช้าเล็กน้อย ... ) นอกจากนี้ยังทำให้คำแนะนำโดยเฉลี่ยอีกเล็กน้อย - ซึ่งหมายความว่าเมื่อใช้งานโปรแกรมที่ขึ้นอยู่กับแบนด์วิดธ์หน่วยความจำคำสั่งการลงทะเบียนพิเศษของคุณจะทำให้คุณช้าลงจริง ๆ !
หากซีพียูของคุณเป็นไปตามลำดับและไม่ทำการเปลี่ยนชื่อรีจิสเตอร์และคุณกำลังพยายามดำเนินการหลายอย่างต่อรอบ (มากกว่า 3) ในทางทฤษฎีแล้วคุณต้องลงทะเบียนมากขึ้นเนื่องจากจำนวน ops ต่อรอบเพิ่มขึ้น นี่คือสาเหตุที่ Itanium มีการลงทะเบียนมากมาย! แต่ในทางปฏิบัตินอกจากโค้ดเชิงตัวเลขหรือ floating-point หรือ SIMD (ซึ่ง Itanium ทำได้ดีมาก) โค้ดส่วนใหญ่จะมีหน่วยความจำอ่าน / เขียนและกระโดดจำนวนมากซึ่งทำให้ความฝันของ ops มากกว่า-3 ต่อวงจรเป็นไปไม่ได้ (โดยเฉพาะในซอฟต์แวร์ที่มุ่งเน้นเซิร์ฟเวอร์เช่นฐานข้อมูลคอมไพเลอร์การใช้ภาษาระดับสูงเช่นจาวาสคริปต์การจำลอง ฯลฯ ... ) นี่คือสิ่งที่ Itanium จมลง
ทุกอย่างลงมาเพื่อความแตกต่างระหว่างการคำนวณและการดำเนินการ!
ใครบอกคุณว่าโปรเซสเซอร์มีการลงทะเบียน 32 ครั้งเสมอ ? x86 มี 8, ARM 32 บิตและ x86_64 มี 16, IA-64 มี 128 และตัวเลขอื่น ๆ อีกมากมาย คุณสามารถดูได้ที่นี่ แม้แต่ MIPS, PPC หรือสถาปัตยกรรมใด ๆ ที่มีการลงทะเบียนวัตถุประสงค์ทั่วไป 32 รายการในชุดคำสั่งนั้นมีขนาดใหญ่กว่า 32 เนื่องจากยังคงมีการลงทะเบียน (ถ้ามี) เสมอ, การลงทะเบียนควบคุม ... ไม่รวมถึงการลงทะเบียนเปลี่ยนชื่อและการลงทะเบียนฮาร์ดแวร์
ทุกอย่างมีราคา จำนวนของการลงทะเบียนที่มากขึ้นยิ่งคุณมีงานมากขึ้นเมื่อทำการสลับงานเพิ่มพื้นที่ที่คุณต้องการในการเข้ารหัสคำสั่ง หากคุณมีการลงทะเบียนน้อยคุณไม่จำเป็นต้องจัดเก็บและกู้คืนมากเมื่อโทรและกลับจากฟังก์ชั่นหรือสลับงานกับการแลกเปลี่ยนการขาดการลงทะเบียนในบางรหัสที่ครอบคลุม
ยิ่งไฟล์ register มีขนาดใหญ่เท่าใดก็ยิ่งมีความซับซ้อนและราคาสูงขึ้นเท่านั้น SRAM เป็น RAM ที่เร็วที่สุดและแพงที่สุดดังนั้นจึงใช้ในแคชของ CPU เท่านั้น แต่ก็ยังถูกกว่ามากและใช้พื้นที่น้อยกว่าไฟล์ register ที่มีความจุเท่ากัน
ตัวอย่างเช่นโปรเซสเซอร์ Intel ทั่วไปมี "เป็นทางการ" 16 จำนวนเต็มและ 16 เวกเตอร์ลงทะเบียน แต่ในความเป็นจริงแล้วยังมีอีกมากมาย: โปรเซสเซอร์ใช้ "register renaming" หากคุณมีคำสั่ง reg3 = reg1 + reg2 คุณจะมีปัญหาหากคำสั่งอื่นที่ใช้ reg3 ยังไม่เสร็จ - คุณไม่สามารถเรียกใช้คำสั่งใหม่ในกรณีที่มันเขียนทับ reg3 ก่อนที่คำสั่งก่อนหน้าจะถูกอ่าน
ดังนั้นจึงมีผู้ลงทะเบียนจริงประมาณ 160 คน ดังนั้นคำสั่งง่ายๆข้างต้นจึงเปลี่ยนเป็น "regX = reg1 + reg2 และโปรดจำไว้ว่า regX มี reg3" หากไม่มีการลงทะเบียนเปลี่ยนชื่อการดำเนินการตามคำสั่งจะตายอย่างแน่นอนในน้ำ
ฉันไม่ใช่วิศวกรไฟฟ้า แต่ฉันคิดว่ามีความเป็นไปได้อีกประการสำหรับเหตุผลที่จะ จำกัด จำนวนการลงทะเบียนคือการกำหนดเส้นทาง มีหน่วยเลขคณิตจำนวน จำกัด และพวกเขาจะต้องสามารถนำเข้าจากการลงทะเบียนทุกครั้งและส่งออกไปยังการลงทะเบียนทุกครั้ง นี่เป็นเรื่องจริงโดยเฉพาะอย่างยิ่งเมื่อคุณมีโปรแกรม pipelined ที่สามารถดำเนินการตามคำสั่งได้หลายรอบ
เวอร์ชั่นง่าย ๆ นี้จะมีความซับซ้อนทำให้การเพิ่มจำนวนของรีจิสเตอร์ที่ไม่สามารถปรับขนาดได้หรือต้องมีการออกแบบการกำหนดเส้นทางใหม่ให้มีความซับซ้อนมากขึ้นในการกำหนดเส้นทางทุกอย่างที่ซับซ้อนกว่า
ฉันมีความคิดสำหรับคำตอบนี้จากการดูบางคำพูดของ Ivan Godard เกี่ยวกับ Mill CPU ส่วนหนึ่งของนวัตกรรมของ Mill CPU คือคุณไม่สามารถส่งออกไปยังรีจิสเตอร์โดยพลการเอาท์พุททั้งหมดจะถูกส่งไปยัง register stack หรือ "belt" ซึ่งจะช่วยลดปัญหาการจัดเส้นทางเนื่องจากคุณรู้ว่าจะไปที่ใด โปรดทราบว่าพวกเขายังมีปัญหาการกำหนดเส้นทางสำหรับการรับอินพุตลงในหน่วยเลขคณิต
โปรดดูThe Mill CPU Architecture - Belt (2 of 9)สำหรับคำแถลงปัญหาและแนวทางแก้ไขของ Mill
สำหรับ MIPS ISA, Hennessy และ Patterson, องค์กรคอมพิวเตอร์และการออกแบบรุ่นที่ 4 หน้า 176, ตอบคำถามเฉพาะนี้โดยตรง:
เล็กกว่าเร็วกว่า ความปรารถนาด้านความเร็วคือเหตุผลที่ MIPS มีผู้ลงทะเบียนมากกว่า 32 คน