1 / 18

Register Spilling

Register Spilling. การ ล้นจาก รีจิสเตอร์. Spilling (การล้นจากรีจิสเตอร์). เกิดอะไรขึ้นถ้าทุกๆ node มี neighbor มากกว่า k ตัวอย่างเช่นถ้าเราต้องการทำ 3-coloring ของ RIG ด้านล่างนี้. Spilling (การล้นจากรีจิสเตอร์).

suzy
Télécharger la présentation

Register Spilling

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Register Spilling การล้นจากรีจิสเตอร์

  2. Spilling (การล้นจากรีจิสเตอร์) • เกิดอะไรขึ้นถ้าทุกๆ node มี neighbor มากกว่า k • ตัวอย่างเช่นถ้าเราต้องการทำ 3-coloring ของ RIG ด้านล่างนี้

  3. Spilling (การล้นจากรีจิสเตอร์) • • ถ้าเราลบ node หนึ่งออกไปตามขั้นตอน heuristics เราจะไปต่อไปได้ดังแสดงด้วยรูป RIG ใหม่ต้านล่าง • • ในกรณีนี้เราจะทำการเลือก node ที่จะ spill • – ตัวแปรที่ถูก spill ไปจะไป “lives” ในหน่วยความจำหลักแทน • – ให้ว่าเราเลือก f ที่จะต้องถูก spill ไปที่หน่วยความจำหลัก

  4. Spilling (การล้นจากรีจิสเตอร์) • หลังจากที่เรา spill f แล้ว เราสามารถกลับไปใช้ heuristic ได้เหมือนเดิม (ดูจากภาพ RIG ด้านล่าง)

  5. Spilling (การล้นจากรีจิสเตอร์) • ในท้ายที่สุดเราก็จะต้องให้ค่าสีกับ f โดยความคาดหวังของเราก็คือจาก neighbor ทั้ง 4 ของ f นั้น บางทีอาจจะมีสีที่ใช้แตกต่างกัน น้อยกว่า 3 สีก็เป็นได้

  6. Spilling • ในกรณีนี้ไม่เป็นเช่นที่เราคาดหวัง • เราจะต้องทำการจองตำแหน่งในหน่วยความจำหลักให้กับ f • ส่วนใหญ่ใช้พื้นที่บน stack และจัดให้อยู่ใน AR • เรียนตำแหน่งนี้ว่า fa • ในกรณีที่มีการใช้ f ให้เพิ่มคำสั่ง load เพื่อนำข้อมูลเข้าเข้ามาที่ f f := load fa • ในกรณีที่มีการ assign ค่าให้ f (การ write ไปที่ f) ให้ใส่คำสั่ง store ต่อไปนี้ store f, fa

  7. ตัวอย่าง Spilling • โค๊ดใหม่หลังจากการ spill ตัวแปร f

  8. ค่า Livenessเดิม

  9. คำนวณ Livenessใหม่

  10. คำนวณ Livenessใหม่ • ข้อมูล livenessที่คำนวณได้ใหม่มีความใกล้เคียงกับ livenessเดิมมาก (สำหรับ CFG ที่ไม่มีการ spill) • f จะ live ในช่วงต่อไปนี้ • ระหว่าง f := load faและคำสั่งที่อยู่ถัดไป • ระหว่าง f := load faและคำสั่งที่อยู่ก่อนหน้านี้ • การทำ spilling ลดช่วงชีวิต (live range) ของ f • เพราะฉะนั้นทำให้ interference (การทับหรือรบกวนกันของตัวแปร) ลดลง • ซึ่งทำให้ node ของ f ใน RIG มี neighbor ที่น้อยลง

  11. คำนวณ RIG ใหม่หลังจาก Spilling • Edge หลังจากที่ node ที่ทำการ spill จะถูกกำจัดออกจาก RIG เดิม • ตัวแปร f live range ยังทับซ้อนกับ live range ของ c และ d • ได้ RIG ใหม่ที่สามารถใช้เพียง 3 สีในการให้สี RIG นี้ได้ (3-colorable)

  12. การตัดสินใจเกี่ยวกับ Spilling • ในบางครั้งเราอาจจะต้อง spill มากกว่าหนึ่งครั้งก่อนที่จะทำ coloring จากจำนวนสีที่กำหนดให้อย่างจำกัดได้ • เราสามารถเลือกที่จะ spill ตัวแปรตัวใดก็ได้ อัลกอริทึมที่กล่าวมายังคงทำงานได้ถูกต้อง • แต่การเลือกที่ดีจะช่วยเพิ่มประสิทธิภาพของโค๊ด assembly ที่ผลิตได้ • มี heuristics ที่ใช้ในการเลือกต่อไปนี้: • Spill ตัวแปรที่ทำให้เกิด interference มากที่สุด (นั่นคือมี neighbor มากที่สุด) • Spill ตัวแปรที่ใช้งานน้อย • หลีกเลี่ยงการ spill ใน inner loop

  13. ประเด็นหลักเกี่ยวกับ Register Allocation • คอมไพเลอร์ในปัจจุบันทำ optimization อันนี้ทั้งนั้น • เพราะสมรรถนะที่แตกต่างกันมากระหว่าง CPU กับ memory การคำนวณที่เกี่ยวข้องกับตัวแปรที่อยู่ในรีจิสเตอร์จะทำได้เร็วกว่าตัวแปรที่อยู่ใน memory มาก • การผลิตโค๊ดในสไตล์ stack machine จะมีสมรรถนะต่ำมากเพราะมีการโต้ตอบกับ memory มาก • การทำ register allocation สำหรับ CISC จะยุ่งยากมากกว่า RISC • รีจิสเตอร์แต่ละตัวมีสิ่งที่พิเศษเฉพาะตัว อาจจะไม่สามารถนำมาใส่ตัวแปรบางชนิดในทุกๆกรณีได้

  14. ลำดับชั้นของระบบหน่วยความจำ(Memory Hierarchy)

  15. การจัดการหน่วยความจำลำดับชั้นการจัดการหน่วยความจำลำดับชั้น • ภาพของหน่วยความจำที่โปรแกรมเมอร์เห็นคือที่เก็บข้อมูลที่มีตำแหน่งติดกันและมีความจุเป็นอนันต์และมีประสิทธิภาพสูง (Virtual Memory) • CPU OS และคอมไพเลอร์จะทำหน้าที่จัดการลำดับชั้นของหน่วยความจำเพื่อให้ภาพในอุดมคตินั้นกับโปรแกรมเมอร์ • ในโลกความเป็นจริงลำดับชั้นของหน่วยความจำมีความจำกัดทางด้านความจุและสมรรถนะ • CPU OS และ คอมไพเลอร์จะต้อง “ซ่อน” ข้อจำกัดนี้และ “หลอก” โปรแกรมเมอร์ให้มองเห็นแต่ในโลกเสมือน • CPU จัดการในส่วนที่เกี่ยวข้องกับ main memory และ cache • คอมไพเลอร์จัดการในส่วนการบริหารรีจิสเตอร์และการติดต่อกับ main memory • OS จัดการในส่วนที่เกี่ยวข้องกับ main memory และ disc

  16. Cache • คอมไพเลอร์เก่งเรื่องการจัดการรีจิสเตอร์ • ถ้าเราต้องการให้คอมไพเลอร์ช่วย CPU ในการจัดการ cache • ทำได้ระดับหนึ่งแต่คอมไพเลอร์ไม่เก่งมาก • หลายๆอย่างโปรแกรมเมอร์ต้องออกมาจากโลกเสมือนเพื่อช่วยคอมไพเลอร์ • เป็นหนึ่งในแนวทางการวิจัยทางด้านคอมไพเลอร์ในปัจจุบัน

  17. การ Optimize การใช้ Cache • พิจารณา loop ด้านล่างนี้ for(j := 1; j < 10; j++) for(i=1; i<10000000; i++) a[i] *= b[i] • Loop นี้มีประสิทธิภาพต่ำเพราะมีการใช้งาน cache อย่างไม่มีประสิทธิภาพ • ทุกๆการอ้างถึงค่าใน a[i] หรือ b[i] เป็นการ miss ทั้งหมด (ให้ว่า cache block มีขนาดเท่ากับหนึ่ง element ของ a และ b)

  18. การ Optimize การใช้ Cache • พิจารณาการเขียนโปรแกรมใหม่จากสไลด์ที่แล้วดังนี้: for(i=1; i<10000000; i++) for(j := 1; j < 10; j++) a[i] *= b[i] – ให้ผลลัพธ์เหมือนกันแต่สมรรถนะของโปรแกรมนี้สูงขึ้นมาก – การใช้ประโยชน์จาก cache ทำได้สูงสุด – สมรรถนะที่เพิ่มขึ้นอาจจะมากกว่า 10 เท่า • Optimization ในลักษณะนี้ (เรียกว่า loop interchange) คอมไพเลอร์สามารถทำได้ • อาจจะต้องทำในระดับ high-level IR

More Related