3

我有一个带有 CC 3.0 的 GPU,所以它应该支持 16 个并发内核。我通过循环 clEnqueueNDRangeKernel 10 次来启动 10 个内核。我如何知道内核是同时执行的?

我想到的一种方法是在 NDRangeKernel 语句之前和之后获取时间。我可能不得不使用事件来确保内核的执行已经完成。但我还是觉得循环会顺序启动内核。有人可以帮我吗..

4

3 回答 3

13

要确定您的内核执行是否重叠,您必须对它们进行分析。这需要几个步骤:

1. 创建命令队列

仅当使用以下属性创建命令队列时才会收集分析数据CL_QUEUE_PROFILING_ENABLE

cl_command_queue queues[10];
for (int i = 0; i < 10; ++i) {
  queues[i] = clCreateCommandQueue(context, device, CL_QUEUE_PROFILING_ENABLE,
                                   &errcode);
}

2. 确保所有内核同时启动

您的假设是正确的,即 CPU 按顺序排列内核。但是,您可以创建单个用户事件并将其添加到所有内核的等待列表中。这会导致内核在用户事件完成之前不开始运行:

// Create the user event
cl_event user_event = clCreateUserEvent(context, &errcode);

// Reserve space for kernel events
cl_event kernel_events[10];

// Enqueue kernels
for (int i = 0; i < 10; ++i) {
  clEnqueueNDRangeKernel(queues[i], kernel, work_dim, global_work_offset,
                         global_work_size, 1, &user_event, &kernel_events[i]);
}

// Start all kernels by completing the user event
clSetUserEventStatus(user_event, CL_COMPLETE);

3. 获取分析时间

最后,我们可以收集内核事件的时间信息:

// Block until all kernels have run to completion
clWaitForEvents(10, kernel_events);

for (int i = 0; i < 10; ++i) {
  cl_ulong start;
  clGetEventProfilingInfo(kernel_event[i], CL_PROFILING_COMMAND_START,
                          sizeof(start), &start, NULL);
  cl_ulong end;
  clGetEventProfilingInfo(kernel_event[i], CL_PROFILING_COMMAND_END,
                          sizeof(end), &end, NULL);
  printf("Event %d: start=%llu, end=%llu", i, start, end);
}

4. 分析输出

现在您有了所有内核运行的开始和结束时间,您可以检查重叠(手动或以编程方式)。输出单位是纳秒。但是请注意,设备计时器仅精确到某个分辨率。您可以使用以下方法查询分辨率:

size_t resolution;
clGetDeviceInfo(device, CL_DEVICE_PROFILING_TIMER_RESOLUTION,
                sizeof(resolution), &resolution, NULL);

FWIW,我在带有 CC 2.0(应该支持并发内核)的 NVIDIA 设备上进行了尝试,并观察到内核是按顺序运行的。

于 2012-08-03T12:33:34.207 回答
1

您可以通过使用C Framework for OpenCL避免其他答案中建议的所有样板代码(顺便说一句是正确的),这大大简化了此任务,并为您提供有关 OpenCL 事件(内核执行、数据传输等)的详细信息),包括专门用于重叠执行所述事件的表格和绘图。

我开发这个库是为了简化其他答案中描述的过程。您可以在此处查看基本用法示例。

于 2013-07-02T15:44:47.423 回答
0

是的,按照您的建议,尝试使用事件,并分析所有 QUEUED、SUBMIT、START、END 值。这些应该是“设备时间”中的绝对值,您可以查看不同内核的处理(开始到结束)是否重叠。

于 2012-08-03T03:08:06.530 回答