PyOpenCL设备入队内核后随机崩溃及线程挂起问题排查
异构OpenCL灰度化任务调度问题
我正在尝试以异构方式执行灰度化处理:将100张图片分配给计算机上所有可用设备,让所有任务同时完成,以此实现比单设备更快的处理效率。
内核代码
我特意在内核中添加了while(1){};语句,目的是观察调度器工作机制,同时让设备在任务上消耗更多时间。代码如下:
__kernel void grayscale(__global uchar *input, __global uchar *output, uint width, ulong size, const ulong chunk_size) { ulong gid_column = get_global_id(0); ulong gid_row = get_global_id(1); ulong pixel; float luma,r,g,b; while(1){}; for(ulong i = 0; i<chunk_size;i++){ pixel = ((gid_column*chunk_size)+(gid_row*width)+i)*3; if(pixel<size-3){ r = input[pixel+0]; g = input[pixel+1]; b = input[pixel+2]; luma = 0.299f * b + 0.587f * g + 0.114f * r; output[pixel+0] = luma; output[pixel+1] = luma; output[pixel+2] = luma; } else break; } }
调度逻辑代码
以下是处理任务分配的Python代码段,逻辑为:先给第一个设备分配任务,后续每次将新任务分配给当前最空闲的设备。
def grayscale(self, images): result = [] device_queues = {} device_queues_status = {} DEBUG_PROCESED_TASKS = {} selected_device = None for device in self.opencl_devices: device_queues[device] = [] device_queues_status[device] = 0 DEBUG_PROCESED_TASKS[device.device_name] = 0 for image in images: for device in device_queues: device_queues_status[ device] = OpenCLFunctions.Pictures.get_work_amount( device_queues[device]) selected_device = min(device_queues_status, key=device_queues_status.get) ev = selected_device._grayscale(image) device_queues[selected_device].append(ev) DEBUG_PROCESED_TASKS[selected_device.device_name] += 1 print(DEBUG_PROCESED_TASKS) def _grayscale(self, input_image): ENQUEUE_PROCESS_ASYNC = opencl_device.enqueue_nd_range_kernel ENQUEUE_COPY_ASYNC = opencl_device.enqueue_copy OPENCL_BUFFER = opencl_device.Buffer program = self.kernels["_grayscale"].grayscale buffers = OpenCLBuffer( OPENCL_BUFFER(self.context, opencl_device.mem_flags.READ_WRITE | opencl_device.mem_flags.ALLOC_HOST_PTR, size=input_image.size), OPENCL_BUFFER(self.context, opencl_device.mem_flags.READ_WRITE | opencl_device.mem_flags.ALLOC_HOST_PTR, size=input_image.size)) input_copy = ENQUEUE_COPY_ASYNC(self.queue, buffers.opencl_buffer_input, input_image, is_blocking=False) program.set_args( buffers.opencl_buffer_input, buffers.opencl_buffer_output, opencl_device_numpy.uint32(input_image.shape[0]), opencl_device_numpy.uint64(buffers.size), opencl_device_numpy.uint64(self.CHUNK_PROCESSING_SIZE)) max_work_group_size_kernel = program.get_work_group_info( opencl_device.kernel_work_group_info.WORK_GROUP_SIZE, self.device) prefered_local_size = program.get_work_group_info( opencl_device.kernel_work_group_info. PREFERRED_WORK_GROUP_SIZE_MULTIPLE, self.device) global_size = OpenCLFunctions.Pictures._get_global_size_picture( input_image.shape[0], input_image.shape[1], self.CHUNK_PROCESSING_SIZE) local_size, global_size = OpenCLFunctions.OpenCLScheduler._get_optimal_local_global_size( global_size, max_work_group_size_kernel, self.device.max_work_group_size, self.device.max_work_item_sizes, prefered_local_size) try: ev = ENQUEUE_PROCESS_ASYNC(self.queue, program, global_size, local_size, wait_for=[input_copy]) return [ev, buffers.opencl_buffer_output] except Exception as e: print(e)
遇到的问题
调用ev = selected_device._grayscale(image)后,调试器无法查看变量,Python主线程挂起;内核入队后虽能运行一小段时间,但表现不稳定。
已尝试的解决方法
- 阻止Python垃圾回收器回收事件对象
- 用长循环替代
while(1){}; - 添加变量监控以追踪调度器处理后的忙碌事件
- 使用更小的数据集
预期行为
因GPU上的while(1){};语句导致任务处于忙碌状态,调度器应识别到该设备忙碌,进而将下一个任务分配给其他设备(如CPU或核显)。
请问我是否遗漏了什么关键环节?(注:此问题仅用于研究实验,我希望理解该特定问题的成因。)
内容的提问来源于stack exchange,提问作者Seeven
相关产品推荐
相关产品推荐

