CUDA khai thác mô hình lập trình nhiều dữ liệu hướng dẫn (SIMD). Các chủ đề tính toán được tổ chức theo các khối và các khối chuỗi được gán cho một bộ xử lý đa luồng (SM) khác nhau. Việc thực thi khối luồng trên SM được thực hiện bằng cách sắp xếp các luồng trong warps của 32
luồng: mỗi warp hoạt động trong khóa bước và thực hiện chính xác lệnh cùng một dữ liệu khác nhau.
Nói chung, để lấp đầy GPU, hạt nhân được khởi chạy với nhiều khối hơn có thể thực sự được lưu trữ trên các SM. Vì không phải tất cả các khối có thể được lưu trữ trên một SM, một trình lên lịch làm việc thực hiện một chuyển đổi ngữ cảnh khi một khối đã kết thúc tính toán. Cần lưu ý rằng việc chuyển đổi các khối được quản lý hoàn toàn bằng phần cứng bởi bộ lập lịch và lập trình viên không có phương tiện ảnh hưởng đến cách các khối được lên lịch cho SM. Điều này cho thấy một giới hạn cho tất cả các thuật toán không hoàn toàn phù hợp với một mô hình lập trình SIMD và có sự mất cân bằng công việc. Thật vậy, một khối A
sẽ không được thay thế bởi một khối khác B
trên cùng một SM cho đến khi luồng cuối cùng của khối A
sẽ không hoàn thành để thực thi.
Mặc dù CUDA không hiển thị bộ lập lịch phần cứng cho người lập trình, các chủ đề liên tục chủ đề bỏ qua bộ lập lịch phần cứng bằng cách dựa vào hàng đợi công việc. Khi một khối kết thúc, nó sẽ kiểm tra hàng đợi để có thêm công việc và tiếp tục làm như vậy cho đến khi không còn công việc nào nữa, tại thời điểm đó khối đó sẽ nghỉ hưu. Bằng cách này, hạt nhân được khởi chạy với nhiều khối như số lượng SM có sẵn.
Các đề dai dẳng kỹ thuật là tốt hơn minh họa bằng các ví dụ sau đây, mà đã được lấy từ phần trình bày
“GPGPU” computing and the CUDA/OpenCL Programming Model
Một ví dụ chi tiết hơn có sẵn trong các giấy
Understanding the efficiency of ray traversal on GPUs
// Persistent thread: Run until work is done, processing multiple work per thread
// rather than just one. Terminates when no more work is available
// count represents the number of data to be processed
__global__ void persistent(int* ahead, int* bhead, int count, float* a, float* b)
{
int local_input_data_index, local_output_data_index;
while ((local_input_data_index = read_and_increment(ahead)) < count)
{
load_locally(a[local_input_data_index]);
do_work_with_locally_loaded_data();
int out_index = read_and_increment(bhead);
write_result(b[out_index]);
}
}
// Launch exactly enough threads to fill up machine (to achieve sufficient parallelism
// and latency hiding)
persistent<<numBlocks,blockSize>>(ahead_addr, bhead_addr, total_count, A, B);
Có lẽ bạn nên bao gồm một số tài liệu tham khảo cụ thể cho các bài báo nói về "Chủ đề liên tục". –
thực hiện: Nghiên cứu các chủ đề liên tục Lập trình GPU cho khối lượng công việc GPGPU – AmineMs
Bạn có thể nhận thêm một số thông tin chi tiết bổ ích nếu bạn [xem bản trình bày] (http://www.gputechconf.com/gtcnew/on-demand-gtc.php? sessionTopic = & searchByKeyword = S0157 & submit = & select = + & sessionEvent = & sessionYear = 2012 & sessionFormat = # 1337). Đọc của tôi về nó là nó là nhiều hơn hoặc ít hơn như bạn mô tả, có nghĩa là một hạt nhân không thoát ra và liên tục bỏ phiếu cho công việc từ một hàng đợi trong bộ nhớ toàn cầu. –