GPU của tôi đang chờ đợi điều gì?


11

Tôi đang viết chương trình OpenCL để sử dụng với GPU AMD Radeon HD 7800 series. Theo hướng dẫn lập trình OpenCL của AMD , thế hệ GPU này có hai hàng đợi phần cứng có thể hoạt động không đồng bộ.

5.5.6 Hàng đợi lệnh

Đối với Quần đảo phía Nam và sau đó, các thiết bị hỗ trợ ít nhất hai hàng đợi tính toán phần cứng. Điều đó cho phép một ứng dụng tăng thông lượng của các công văn nhỏ với hai hàng đợi lệnh để gửi không đồng bộ và có thể thực thi. Các hàng đợi tính toán phần cứng được chọn theo thứ tự sau: hàng đợi thứ nhất = hàng đợi lệnh OCL, hàng đợi thứ hai = hàng đợi OCL lẻ.

Để làm điều này, tôi đã tạo hai hàng đợi lệnh OpenCL riêng để cung cấp dữ liệu cho GPU. Một cách thô bạo, chương trình chạy trên luồng máy chủ trông giống như thế này:

static const int kNumQueues = 2;
cl_command_queue default_queue;
cl_command_queue work_queue[kNumQueues];

static const int N = 256;
cl_mem gl_buffers[N];
cl_event finish_events[N];

clEnqueueAcquireGLObjects(default_queue, gl_buffers, N);

int queue_idx = 0;
for (int i = 0; i < N; ++i) {
  cl_command_queue queue = work_queue[queue_idx];

  cl_mem src = clCreateBuffer(CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, ...);

  // Enqueue a few kernels
  cl_mem tmp1 = clCreateBuffer(CL_READ_WRITE);
  clEnqueueNDRangeKernel(kernel1, queue, src, tmp1);

  clEnqueueNDRangeKernel(kernel2, queue, tmp1, tmp1);

  cl_mem tmp2 = clCreateBuffer(CL_READ_WRITE);
  clEnqueueNDRangeKernel(kernel2, queue, tmp1, tmp2);

  clEnqueueNDRangeKernel(kernel3, queue, tmp2, gl_buffer[i], finish_events + i);

  queue_idx = (queue_idx + 1) % kNumQueues;
}

clEnqueueReleaseGLObjects(default_queue, gl_buffers, N);
clWaitForEvents(N, finish_events);

Với kNumQueues = 1, ứng dụng này hoạt động khá nhiều như dự định: nó tập hợp tất cả các công việc vào một hàng lệnh duy nhất sau đó chạy đến khi hoàn thành với GPU khá bận rộn suốt thời gian. Tôi có thể thấy điều này bằng cách nhìn vào đầu ra của trình lược tả CodeXL:

nhập mô tả hình ảnh ở đây

Tuy nhiên, khi tôi đặt kNumQueues = 2, tôi hy vọng điều tương tự sẽ xảy ra nhưng với công việc chia đều cho hai hàng đợi. Nếu có bất cứ điều gì, tôi hy vọng mỗi hàng đợi có các đặc điểm riêng giống như một hàng đợi: nó bắt đầu hoạt động tuần tự cho đến khi mọi thứ được thực hiện. Tuy nhiên, khi sử dụng hai hàng đợi, tôi có thể thấy rằng không phải tất cả các công việc được chia thành hai hàng đợi phần cứng:

nhập mô tả hình ảnh ở đây

Khi bắt đầu công việc của GPU, các hàng đợi quản lý để chạy một số hạt nhân không đồng bộ, mặc dù có vẻ như không bao giờ chiếm hết các hàng đợi phần cứng (trừ khi hiểu lầm của tôi). Gần cuối GPU hoạt động, có vẻ như các hàng đợi đang thêm công việc liên tục vào một trong các hàng đợi phần cứng, nhưng thậm chí có những lúc không có hạt nhân nào đang chạy. Đưa cái gì? Tôi có một số hiểu lầm cơ bản về cách chạy thời gian được cho là hành xử?

Tôi có một vài lý thuyết về lý do tại sao điều này xảy ra:

  1. Các clCreateBuffercuộc gọi xen kẽ đang buộc GPU phân bổ tài nguyên thiết bị từ nhóm bộ nhớ dùng chung một cách đồng bộ, giúp ngăn chặn việc thực thi các hạt nhân riêng lẻ.

  2. Việc triển khai OpenCL cơ bản không ánh xạ các hàng đợi logic đến các hàng đợi vật lý và chỉ quyết định nơi đặt các đối tượng khi chạy.

  3. Vì tôi đang sử dụng các đối tượng GL, GPU cần đồng bộ hóa quyền truy cập vào bộ nhớ được phân bổ đặc biệt trong quá trình ghi.

Có bất kỳ giả định nào trong số này là đúng không? Có ai biết điều gì có thể khiến GPU phải chờ trong kịch bản hai hàng không? Bất kỳ và tất cả cái nhìn sâu sắc sẽ được đánh giá cao!


Tôi không thể tìm thấy nơi nó nói có hai hàng đợi phần cứng trong hướng dẫn lập trình. Bạn có thể gửi một trích dẫn từ tài liệu? Đề cập đến chương nào nói rằng có hai hàng đợi? Số lượng hàng đợi phần cứng có thể truy vấn được trong thời gian chạy bằng OpenCL không?
Andreas

Tôi đã cập nhật bài viết của mình. Nó nói có thể thực thi, nhưng nếu nó có thể làm một vài lý do tại sao nó không thể làm tất cả? Ngoài ra, thời gian chạy OpenCL không có khái niệm về hàng đợi phần cứng, vì vậy đây không phải là thứ mà bạn có thể truy vấn.
Mokosha

Câu trả lời:


2

Tính toán hàng đợi nói chung không nhất thiết có nghĩa là bây giờ bạn có thể thực hiện các công văn gấp đôi. Một hàng đợi duy nhất bão hòa đầy đủ các đơn vị tính toán sẽ có thông lượng tốt hơn. Nhiều hàng đợi rất hữu ích nếu một hàng đợi tiêu tốn ít tài nguyên hơn (bộ nhớ dùng chung hoặc các thanh ghi), sau đó hàng đợi thứ cấp có thể chồng lên nhau trên cùng một đơn vị tính toán.

Đối với kết xuất thời gian thực, đây là trường hợp đặc biệt với những thứ như kết xuất bóng rất nhẹ trên máy tính / đổ bóng nhưng nặng về phần cứng chức năng cố định, do đó giải phóng bộ lập lịch GPU để chạy không đồng bộ hàng đợi thứ cấp.

Cũng tìm thấy điều này trong các ghi chú phát hành. Không biết đó có phải là vấn đề tương tự không, nhưng có thể là CodeXL không tuyệt vời. Tôi hy vọng rằng nó có thể không có thiết bị tốt nhất cho các công văn đang bay.

https://developer.amd.com/wordpress/media/2013/02/AMD_CodeXL_Release_Notes.pdf

Đối với một ứng dụng thực hiện đồng thời truyền dữ liệu không đồng bộ và thực thi kernel, dòng thời gian được hiển thị trong chế độ xem phiên Trace ứng dụng sẽ không hiển thị các hoạt động này bị chồng chéo. Điều này là do trình điều khiển và phần cứng buộc các hoạt động này phải đồng bộ trong khi định hình. (333981)

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.