我想测量 OpenCL 内核在循环中的执行时间。当我使用
clGetEventProfilingInfo()
来测量排队、提交和启动内核的时间时,与实际执行时间相比,我在内核提交和设备上开始执行之间的时间遇到了巨大的开销。我使用以下结构来分析内核:
cl_command_queue queue;
queue = clCreateCommandQueue(context, device_id, CL_QUEUE_PROFILING_ENABLE, &err);
clEnqueueWriteBuffer(queue, kernel_data_d, CL_TRUE, 0,
sizeof(cl_float) * kernel_data_size,
kernel_data_h, 0, NULL, NULL);
for (int i = 0; i < N; ++i) {
cl_event test;
clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &global, &local, 0, NULL, &test);
clWaitForEvents(1 , &test);
clFinish(queue);
clGetEventProfilingInfo(test, CL_PROFILING_COMMAND_SUBMIT, sizeof(time_start), &time_start, NULL);
clGetEventProfilingInfo(test, CL_PROFILING_COMMAND_START, sizeof(time_end), &time_end, NULL);
time_passed_kernel += (time_end-time_start)/1e6;
clReleaseEvent(test);
}
内核提交后开始执行平均需要350ms左右,实际执行平均只需61ms。这个开销有什么具体原因吗?内核访问的数据在GPU上,并且内核已经编译完成。我使用的是 Snapdragon 8 gen 1 SoC 的集成 Adern 730 GPU。
我似乎遇到了我使用的 Adreno GPU 的内部电源管理问题。由于 GPU 在内核执行之间处于空闲状态,GPU 可能会转向较低的功率级别,因此需要很长时间(几毫秒)才能再次激活下一个内核。