我的GPU正在等待什么?


11

我正在编写一个与我的AMD Radeon HD 7800系列GPU一起使用的OpenCL程序。根据AMD的OpenCL编程指南,这一代GPU具有两个可以异步操作的硬件队列。

5.5.6命令队列

对于Southern Islands及更高版本,设备至少支持两个硬件计算队列。这样一来,应用程序就可以通过两个用于异步提交和可能执行的命令队列来提高小型调度的吞吐量。硬件计算队列按以下顺序选择:第一个队列=偶数OCL命令队列,第二个队列=奇数OCL队列。

为此,我创建了两个单独的OpenCL命令队列,以将数据提供给GPU。大致来说,在主机线程上运行的程序如下所示:

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);

使用kNumQueues = 1,该应用程序几乎可以按预期工作:将所有工作收集到一个命令队列中,然后运行,直到GPU一直很忙。通过查看CodeXL分析器的输出,可以看到以下内容:

在此处输入图片说明

但是,当我设置时kNumQueues = 2,我希望发生同样的事情,但是工作会平均分配到两个队列中。如果有的话,我希望每个队列分别具有与一个队列相同的特征:依次开始工作,直到一切完成。但是,当使用两个队列时,我可以看到并非所有工作都分散在两个硬件队列中:

在此处输入图片说明

在GPU的工作开始时,队列确实设法异步运行了一些内核,尽管似乎两个队列都没有完全占据硬件队列(除非我误解了)。在GPU工作快要结束时,队列似乎只向一个硬件队列按顺序添加工作,但有时甚至没有内核在运行。是什么赋予了?我对运行时应该如何运行有基本的误解吗?

关于发生这种情况的原因,我有一些理论:

  1. 散布的clCreateBuffer调用迫使GPU同步地从共享内存池中分配设备资源,这使单个内核的执行停滞了。

  2. 底层的OpenCL实现不会将逻辑队列映射到物理队列,而仅决定运行时在何处放置对象。

  3. 因为我使用的是GL对象,所以GPU需要在写入过程中同步访问对专门分配的内存。

这些假设是否正确?有谁知道在两队列情况下导致GPU等待的原因是什么?任何见解将不胜感激!


我在编程指南中找不到它说有两个硬件队列的位置。您能发表这份文件的报价吗?提到哪一章说有两个队列?使用OpenCL在运行时是否可以查询硬件队列的数量?
安德烈亚斯

我已经更新了我的帖子。它确实表示可能的执行,但是如果可以执行,为什么不能全部执行呢?另外,OpenCL运行时没有硬件队列的概念,因此您无法查询。
Mokosha

Answers:


2

通常,计算队列不一定意味着您现在可以并行执行2x调度。完全饱和计算单元的单个队列将具有更好的吞吐量。如果一个队列消耗较少的资源(共享内存或寄存器),则多个队列很有用,然后辅助队列可以在同一计算单元上重叠。

对于实时渲染,尤其是阴影渲染之类的情况,在计算/着色器上非常轻便,而在固定功能硬件上却很繁重,因此释放了GPU调度程序以运行辅助队列异步。

也可以在发行说明中找到。不知道这是否是同一问题,但可能仅仅是CodeXL不好。我希望它可能没有最好的仪器来进行调度。

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

对于同时执行异步数据传输和内核执行的应用程序,“应用程序跟踪”会话视图中显示的时间线不会显示这些操作重叠。这是因为驱动程序和硬件在配置文件时强制这些操作同步。(333981)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.