ทำไมการห้ามเรียกซ้ำใน OpenCL


19

ฉันต้องการใช้ OpenCL เพื่อเร่งการเรนเดอร์ภาพเรย์ท แต่ฉันสังเกตเห็นว่าหน้าวิกิพีเดียอ้างว่าการห้ามเรียกซ้ำนั้นเป็นสิ่งต้องห้ามใน Open CL มันเป็นเรื่องจริงเหรอ? ในขณะที่ฉันใช้การเรียกซ้ำอย่างครอบคลุมเมื่อต้องทำการเรย์ทติ้งนี่จะต้องใช้การออกแบบจำนวนมากเพื่อให้ได้ประโยชน์จากความเร็วที่เพิ่มขึ้น ข้อ จำกัด พื้นฐานที่ป้องกันการเรียกซ้ำคืออะไร มีวิธีใดบ้างไหม?


2
GPUs ทำงานในวิธีที่แตกต่าง (สถาปัตยกรรมบางอย่าง) ไม่มีแนวคิดเกี่ยวกับ "โปรแกรมสแต็ก" ทั่วโลกดังนั้นการเรียกใช้ฟังก์ชันแบบเรียกซ้ำจึงไม่สามารถทำได้ OpenCL อาจใช้ตัวหารร่วมที่ต่ำที่สุดจึงไม่อนุญาตให้พกพาข้าม GPU ได้อย่างสมบูรณ์ ฮาร์ดแวร์ CUDA รุ่นใหม่ดูเหมือนว่าจะมีการนำเสนอการสนับสนุนสำหรับการเรียกซ้ำในบางจุด: stackoverflow.com/q/3644809/1198654
glampert

คำตอบ:


27

นั่นเป็นเพราะ GPU บางรุ่นเท่านั้นที่สามารถรองรับการเรียกใช้ฟังก์ชั่นและแม้ว่าจะทำได้การเรียกใช้ฟังก์ชันอาจช้าหรือมีข้อ จำกัด เช่นความลึกของสแต็กน้อยมาก

รหัส Shader และรหัสคำนวณ GPU อาจดูเหมือนว่าจะมีการเรียกใช้ฟังก์ชั่นทั่วทุกสถานที่ แต่ภายใต้สถานการณ์ปกติพวกมันจะถูกคอมไพล์เลอร์ 100% รหัสเครื่องที่ดำเนินการโดย GPU บรรจุกิ่งและลูป แต่ไม่มีการเรียกใช้ฟังก์ชัน อย่างไรก็ตามการเรียกฟังก์ชันแบบเรียกซ้ำไม่สามารถ inline ได้ด้วยเหตุผลที่ชัดเจน (เว้นแต่อาร์กิวเมนต์บางตัวเป็นค่าคงที่เวลาคอมไพล์ในลักษณะที่คอมไพเลอร์สามารถพับและอินไลน์ต้นไม้ทั้งหมดของการเรียก)

ในการใช้งานการเรียกใช้ฟังก์ชันจริงคุณต้องมีสแต็ก ส่วนใหญ่แล้วรหัส shader ไม่ได้ใช้สแต็กเลย - GPU มีไฟล์ลงทะเบียนขนาดใหญ่และตัวเฉดสีสามารถเก็บข้อมูลทั้งหมดของพวกเขาในการลงทะเบียนตลอดเวลา เป็นการยากที่จะทำให้ stack ทำงานได้เพราะ (a) คุณต้องการพื้นที่สแต็คจำนวนมากเพื่อให้ warps ทั้งหมดที่สามารถบินได้ในแต่ละครั้งและ (b) ระบบหน่วยความจำ GPU ได้รับการปรับแต่งให้เหมาะสำหรับการรวมกันเป็นจำนวนมาก การทำธุรกรรมของหน่วยความจำเพื่อให้ได้ปริมาณงานสูง แต่สิ่งนี้มาจากความล่าช้าดังนั้นฉันเดาว่าการทำงานแบบกองซ้อนเช่นการบันทึก / เรียกคืนตัวแปรในเครื่องจะช้ามาก

ในอดีตการเรียกใช้ฟังก์ชั่นระดับฮาร์ดแวร์นั้นไม่ได้มีประโยชน์กับ GPU มากนัก ดังนั้นสถาปนิก GPU จึงไม่ได้เน้นไปที่การทำให้เร็ว อาจมีการแลกเปลี่ยนที่แตกต่างกันบางอย่างหากมีความต้องการการเรียกระดับฮาร์ดแวร์ที่มีประสิทธิภาพในอนาคต แต่ (เช่นเดียวกับทุกอย่างในด้านวิศวกรรม) มันจะต้องเสียค่าใช้จ่ายที่อื่น

เท่าที่เรย์ทรัคเป็นห่วงวิธีที่ผู้คนมักจะจัดการกับสิ่งนี้คือการสร้างคิวรังสีที่อยู่ในกระบวนการของการติดตาม แทนที่จะเพิ่มการเรียกซ้ำคุณเพิ่มเรย์ลงในคิวและในระดับสูงคุณจะมีลูปที่คอยประมวลผลจนกว่าคิวทั้งหมดจะว่างเปล่า แม้ว่าจะต้องมีการจัดระเบียบรหัสการเรนเดอร์ใหม่อย่างมีนัยสำคัญหากคุณเริ่มต้นจาก raytracer แบบคลาสสิก สำหรับข้อมูลเพิ่มเติมกระดาษดีในการอ่านเกี่ยวกับเรื่องนี้เป็นคลื่นเส้นทางติดตาม


6
ฉันลังเลที่จะแบ่งปันซอสสูตรลับนี้ แต่ฉันโชคดีมากที่มีจำนวนตีกลับคงที่สูงสุดและมีสแต็กขนาดคงที่ (และวนซ้ำกับจำนวนรอบคงที่ซ้ำ) เพื่อจัดการเรื่องนี้ นอกจากนี้ (และนี่คือซอสลับอย่างแท้จริง imo!) ฉันมีวัสดุของฉันทั้งแบบไตร่ตรองหรือหักเห แต่ไม่เคยทำทั้งสองอย่างซึ่งจะทำให้รังสีไม่แตกเมื่อพวกมันเด้ง ผลลัพธ์สุดท้ายของทั้งหมดนี้คือการเรนเดอร์เรย์เรย์แบบเรียกซ้ำ แต่ผ่านการวนซ้ำขนาดคงที่ไม่ใช่การเรียกซ้ำ
Alan Wolfe

เหมือนการเรียกซ้ำหาง
Tanmay Patil

คุณไม่จำเป็นต้องใช้สแต็กเพื่อทำการเรียกซ้ำแบบหางเนื่องจากฟังก์ชั่นแบบเรียกซ้ำแบบหางสามารถแปลงเป็นฟังก์ชั่นวนซ้ำได้ คอมไพเลอร์ OpenCL ไม่ทำสิ่งนี้โดยอัตโนมัติหรือไม่?
Anderson Green
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.