Tại sao đệ quy bị cấm trong OpenCL?


19

Tôi muốn sử dụng OpenCL để tăng tốc kết xuất hình ảnh raytraced, nhưng tôi nhận thấy rằng trang Wikipedia tuyên bố rằng đệ quy bị cấm trong Open CL. Điều này có đúng không? Khi tôi sử dụng rộng rãi đệ quy khi raytracing, điều này sẽ đòi hỏi một lượng thiết kế lại đáng kể để hưởng lợi từ việc tăng tốc. Các hạn chế cơ bản ngăn ngừa đệ quy là gì? Có cách nào xung quanh nó?


2
GPU hoạt động theo một cách khác. (Một số kiến ​​trúc) không có khái niệm về "ngăn xếp chương trình" toàn cầu, vì vậy các lệnh gọi hàm đệ quy là không thể thực hiện được trong các lệnh đó. OpenCL có thể chấp nhận mẫu số chung thấp nhất, do đó không cho phép nó hoàn toàn di động trên các GPU. Phần cứng CUDA mới hơn dường như đã giới thiệu hỗ trợ cho đệ quy tại một số điểm: stackoverflow.com/q/3644809/1198654
glampert

Câu trả lời:


27

Về cơ bản, đó là vì không phải tất cả các GPU đều có thể hỗ trợ gọi chức năng và thậm chí nếu có thể, các cuộc gọi chức năng có thể khá chậm hoặc có những hạn chế như độ sâu ngăn xếp rất nhỏ.

Mã Shader và mã tính toán GPU có thể có các lệnh gọi chức năng ở mọi nơi, nhưng trong các trường hợp thông thường, tất cả chúng đều được trình biên dịch 100% nội tuyến. Mã máy được thực thi bởi GPU chứa các nhánh và vòng lặp, nhưng không có chức năng gọi. Tuy nhiên, các lệnh gọi hàm đệ quy không thể được đặt trong các lý do rõ ràng. (Trừ khi một số đối số là hằng số thời gian biên dịch, theo cách mà trình biên dịch có thể gấp chúng và nội tuyến toàn bộ cây cuộc gọi.)

Để thực hiện các cuộc gọi chức năng thực sự, bạn cần một ngăn xếp. Hầu hết thời gian, mã shader không sử dụng một ngăn xếp tại tất cả các GPU GPU có các tệp đăng ký lớn và các shader có thể giữ tất cả dữ liệu của chúng trong các thanh ghi trong toàn bộ thời gian. Thật khó để làm cho ngăn xếp hoạt động vì (a) bạn sẽ cần rất nhiều không gian ngăn xếp để cung cấp cho tất cả nhiều sợi dọc có thể bay cùng một lúc và (b) hệ thống bộ nhớ GPU được tối ưu hóa để kết hợp rất nhiều các giao dịch bộ nhớ để đạt được thông lượng cao, nhưng điều này phải trả giá bằng độ trễ, vì vậy tôi đoán là các hoạt động ngăn xếp như lưu / khôi phục các biến cục bộ sẽ rất chậm.

Trong lịch sử, các cuộc gọi chức năng ở mức phần cứng không quá hữu ích trên GPU, vì nó có ý nghĩa hơn trong việc sắp xếp mọi thứ trong trình biên dịch. Vì vậy, các kiến ​​trúc sư GPU đã không tập trung vào việc làm cho chúng nhanh. Có lẽ một số sự đánh đổi khác nhau có thể được thực hiện, nếu có nhu cầu về các cuộc gọi cấp phần cứng hiệu quả trong tương lai, nhưng (như với mọi thứ trong kỹ thuật), nó sẽ phải chịu một chi phí ở nơi khác.

Đối với raytracing có liên quan, cách mọi người thường xử lý loại điều này là bằng cách tạo ra các hàng tia đang trong quá trình truy tìm. Thay vì đệ quy, bạn thêm một tia vào hàng đợi và ở mức cao ở đâu đó bạn có một vòng lặp tiếp tục xử lý cho đến khi tất cả các hàng đợi trống. Mặc dù vậy, nó đòi hỏi phải sắp xếp lại đáng kể mã kết xuất của bạn nếu bạn bắt đầu từ một raytracer đệ quy cổ điển. Để biết thêm thông tin, một bài báo hay để đọc về điều này là Truy tìm đường dẫn sóng .


6
Tôi miễn cưỡng chia sẻ loại nước sốt bí mật này, nhưng tôi đã khá may mắn khi có số lần thoát tối đa cố định và có một ngăn xếp có kích thước cố định (và một vòng lặp với số lần lặp cố định) để xử lý việc này. Ngoài ra (và đây là imo nước sốt bí mật thực sự!) Tôi có tài liệu của mình là phản xạ hoặc khúc xạ nhưng không bao giờ cả hai, điều này làm cho nó không bị tách ra khi chúng bật lên. Kết quả cuối cùng của tất cả điều này là kết xuất kiểu raytraced đệ quy, nhưng thông qua phép lặp kích thước cố định, không phải đệ quy.
Alan Wolfe

Giống như đệ quy đuôi?
Tanmay Patil

Bạn sẽ không cần một ngăn xếp để thực hiện đệ quy đuôi, vì các hàm đệ quy đuôi có thể được chuyển đổi thành các hàm lặp. Trình biên dịch OpenCL không làm điều này tự động?
Anderson Green
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.