ภาพรวมสถาปัตยกรรม tiny-gpu
GPU
- สร้างมาเพื่อรันเคอร์เนลได้ครั้งละหนึ่งตัว
- ในการรันเคอร์เนล ต้องทำขั้นตอนต่อไปนี้:
- โหลดหน่วยความจำโปรแกรมส่วนกลางด้วยโค้ดเคอร์เนล
- โหลดหน่วยความจำข้อมูลด้วยข้อมูลที่จำเป็น
- ระบุจำนวนเธรดที่จะรันในรีจิสเตอร์ควบคุมอุปกรณ์
- ตั้งค่าสัญญาณเริ่มต้นเป็น HIGH เพื่อรันเคอร์เนล
- GPU ประกอบด้วยยูนิตต่อไปนี้:
- รีจิสเตอร์ควบคุมอุปกรณ์
- ตัวดิสแพตเชอร์
- คอร์ประมวลผลจำนวนแปรผัน
- ตัวควบคุมหน่วยความจำสำหรับหน่วยความจำข้อมูลและหน่วยความจำโปรแกรม
- แคช
หน่วยความจำ
- GPU ถูกสร้างมาให้เชื่อมต่อกับหน่วยความจำโกลบอลภายนอก
- หน่วยความจำข้อมูลและหน่วยความจำโปรแกรมแยกจากกันเพื่อความเรียบง่าย
- หน่วยความจำโกลบอลมีแบนด์วิดท์อ่าน/เขียนคงที่
- ตัวควบคุมหน่วยความจำจะติดตามคำขอขาออกทั้งหมดจากคอร์ประมวลผลไปยังหน่วยความจำ ปรับจังหวะคำขอตามแบนด์วิดท์ของหน่วยความจำภายนอกจริง และส่งต่อการตอบกลับจากหน่วยความจำภายนอกไปยังทรัพยากรที่เหมาะสม
- แคชจะเก็บข้อมูลที่ถูกร้องขอซ้ำเพื่อลดการใช้แบนด์วิดท์หน่วยความจำ
คอร์
- แต่ละคอร์มีทรัพยากรสำหรับการประมวลผล
- ใน GPU แบบเรียบง่ายนี้ แต่ละคอร์จะประมวลผลได้ครั้งละหนึ่งบล็อก และมี ALU, LSU, PC และ register file เฉพาะสำหรับแต่ละเธรดภายในบล็อก
- ตัวจัดตารางจะจัดการการรันของเธรด และจะไม่เลือกบล็อกใหม่ก่อนที่บล็อกปัจจุบันจะเสร็จสิ้น
- ตัวดึงคำสั่งจะดึงคำสั่งจาก program counter ปัจจุบันแบบอะซิงโครนัส
- ตัวถอดรหัสจะถอดรหัสคำสั่งที่ดึงมาเป็นสัญญาณควบคุมสำหรับการรันเธรด
- แต่ละเธรดมีชุด register file เฉพาะของตัวเอง
- ALU เป็นหน่วยคำนวณและตรรกะเฉพาะสำหรับแต่ละเธรด
- LSU เป็นหน่วย load-store เฉพาะสำหรับแต่ละเธรดเพื่อเข้าถึงหน่วยความจำข้อมูลโกลบอล
- PC เป็น program counter เฉพาะที่กำหนดคำสั่งถัดไปที่จะรันในแต่ละเธรด
ISA
- มีการติดตั้งใช้งาน ISA แบบง่ายที่มี 11 คำสั่ง
- สร้างขึ้นสำหรับเคอร์เนลง่าย ๆ เช่น การบวกและการคูณเมทริกซ์
- รองรับการคำนวณเลขคณิตพื้นฐาน, การโหลด/จัดเก็บหน่วยความจำ, การแตกแขนง, การโหลดค่าคงที่ เป็นต้น
การทำงาน
- แต่ละคอร์จะผ่านขั้นตอน fetch, decode, request, wait, execute และ update เพื่อรันคำสั่ง
- แต่ละเธรดจะทำตามเส้นทางการทำงานเพื่อคำนวณกับข้อมูลใน register file
- สำหรับความสามารถแบบ SIMD มีค่า block index, dimension และ thread index อยู่ในรีจิสเตอร์แบบอ่านอย่างเดียว
เคอร์เนล
- เขียนเคอร์เนลสำหรับการบวกและคูณเมทริกซ์ด้วย ISA เพื่อสาธิตการเขียนโปรแกรมแบบ SIMD และการรันบน GPU
- สามารถจำลองการรันเคอร์เนลบน GPU ได้ครบถ้วนด้วยไฟล์ทดสอบ พร้อมสร้างสถานะหน่วยความจำข้อมูลและร่องรอยการรัน
การจำลอง
- หลังติดตั้ง iverilog และ cocotb แล้ว สามารถรันการจำลองเคอร์เนลได้ด้วยคำสั่ง make
- ไฟล์ล็อกจะแสดงสถานะหน่วยความจำข้อมูลก่อน/หลัง และร่องรอยการรันทั้งหมดของเคอร์เนล
ฟีเจอร์ขั้นสูง
- ฟีเจอร์เพิ่มเติมจำนวนมากของ GPU สมัยใหม่ที่ช่วยเพิ่มทั้งประสิทธิภาพและความสามารถอย่างมากถูกละไว้เพื่อความเรียบง่าย
- มีการกล่าวถึงฟีเจอร์อย่างแคชหลายชั้นและ shared memory, memory coalescing, pipelining, การจัดตารางแบบ Warp, branch divergence, synchronization และ barriers เป็นต้น
ความเห็นของ GN⁺
- อธิบายแก่นสำคัญของสถาปัตยกรรม GPU และโมเดลการเขียนโปรแกรมแบบ SIMD ได้ดีในแบบที่เรียบง่ายและเข้าใจง่าย โดยเฉพาะผ่านตัวอย่างเคอร์เนลคำนวณเมทริกซ์ที่ช่วยให้เห็นชัดว่าการประมวลผลแบบขนานเกิดขึ้นบน GPU จริงอย่างไร
- ยังสรุปฟีเจอร์ขั้นสูงที่ใช้ใน GPU สมัยใหม่ไว้ได้ดี ทำให้หลังจากเข้าใจ tiny-gpu แล้ว น่าจะช่วยต่อยอดไปศึกษาสถาปัตยกรรม GPU ที่ซับซ้อนยิ่งขึ้นได้
- อย่างไรก็ตาม ฟังก์ชันของกราฟิกส์ไปป์ไลน์จริงไม่ได้รวมอยู่ด้วย จึงไม่ได้พูดถึงว่าฮาร์ดแวร์ที่เฉพาะทางด้านกราฟิกส์ทำงานอย่างไร คนที่สนใจด้านกราฟิกส์อาจรู้สึกเสียดาย
- หากลองเปรียบเทียบกับสถาปัตยกรรม GPU โอเพนซอร์สอื่น ๆ เช่น MIAOW หรือ GPGPU-Sim ก็น่าจะช่วยให้เข้าใจ GPU ที่สมจริงมากขึ้นได้
- หากในอนาคตมีการเพิ่มฟีเจอร์อย่าง branch divergence, memory coalescing และ pipelining ก็มีแนวโน้มว่าจะกลายเป็นสื่อการเรียนรู้ที่ใช้งานได้จริงยิ่งขึ้น อีกทั้งยังน่าสนใจในฐานะโครงการโอเพนซอร์สที่สามารถร่วมพัฒนาได้
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
Intel เผยแพร่เอกสารทางเทคนิคเกี่ยวกับ GPU จำนวนมาก และยังหาแมนนวลของ 810/815 ได้ทางออนไลน์ด้วย นอกจาก 855/910/915/945 แล้ว เอกสารประกอบค่อนข้างมีความสม่ำเสมอ
สนับสนุนงานเกี่ยวกับ GPU แบบโอเพนคอร์
มีอีกโปรเจ็กต์ GPU โอเพนซอร์สชื่อ NyuziProcessor (https://github.com/jbush001/NyuziProcessor)
อยากเริ่มต้นกับ FPGA แต่ยากที่จะรู้ว่าควรเริ่มจากตรงไหน และตัวสาขาเองก็ดูน่าเกรงขาม
เป้าหมายสุดท้ายคือการทำการ์ดเร่งความเร็วสำหรับ LLM (Large Language Model) ซึ่งน่าจะมีหลายส่วนคล้ายกับโปรเจ็กต์นี้ ยกเว้นเรื่อง memory offloading
ตั้งคำถามว่าทำไมถึงผสมตัวดำเนินการกำหนดค่าแบบ non-blocking กับ blocking ภายในบล็อก
alwaysแบบลำดับเคยทำงานคล้ายกันด้วย VHDL มาก่อน บนเว็บ opencores มีโปรเจ็กต์ HDL โอเพนซอร์สอยู่หลากหลาย สงสัยว่าปัจจุบันมีตัวจำลอง HDL แบบกระจายขนาดใหญ่ระดับ HPC หรือไม่ การใช้ GPU สมัยใหม่มาทำการจำลองระดับ RTL ก็ดูสมเหตุสมผล
ชอบที่โปรเจ็กต์ฮาร์ดแวร์ถูกเปิดซอร์ส แต่สิ่งนี้อาจเรียกว่า SIMD coprocessor มากกว่า ถ้าจะเป็น GPU อย่างน้อยก็ควรมีเอาต์พุตแสดงผลบางรูปแบบ แม้ช่วงหลัง Nvidia และรายอื่น ๆ จะขายสถาปัตยกรรมกราฟิกเวอร์ชันสำหรับเซิร์ฟเวอร์ล้วนในชื่อ GPU จนคำนี้หลวมลงไปบ้าง แต่ส่วน "กราฟิก" ในการออกแบบ GPU ก็ยังเป็นแหล่งของความซับซ้อนส่วนใหญ่
สงสัยว่าการที่ ALU จะรองรับคำสั่ง DIV โดยตรงในระดับฮาร์ดแวร์นั้นเป็นเรื่องปกติหรือไม่ ใน CUDA core สมัยใหม่มีการใช้เป็นคำสั่งจริงหรือมักเป็นการจำลองด้วยซอฟต์แวร์มากกว่า วงจรหารจริงบนฮาร์ดแวร์กินพื้นที่มาก จึงไม่คิดว่าจะพบใน ALU ของ GPU การเขียน
DIV: begin alu_out_reg <= rs / rt; endใน Verilog นั้นง่าย แต่บนซิลิคอนมันใช้พื้นที่มาก อย่างไรก็ตาม คนที่จำลองแค่ Verilog อาจไม่รู้ประเด็นนี้เป็น "GPU" อีกตัวที่ไม่มีความสามารถด้านกราฟิก สิ่งแบบนี้ควรถูกเรียกด้วยชื่ออื่น
มีการทำให้ง่ายเกินไปโดยสมมติว่าเธรดถูกประมวลผลแบบขนาน และหลังแต่ละคำสั่งทุกเธรดจะ "มาบรรจบ" กันที่ program counter เดียวกัน แต่ใน GPU จริง เธรดแต่ละตัวสามารถแยกไปคนละ PC ได้ ทำให้เกิด branch divergence ควรลองเขียนโปรแกรม GPU ก่อนจะไปสร้าง GPU ด้วยซิลิคอน และนี่ก็ไม่ใช่ SIMD ด้วยซ้ำ (คนเดียวกับที่ประกอบวงจรกะพริบ LED แล้วอ้างว่าสร้าง CPU)