OpenCL缓冲区分配和映射最佳实践

关于使用OpenCL映射缓冲区的代码是否正确,我有点困惑。

我有两个例子,一个使用CL_MEM_USE_HOST_PTR,一个使用CL_MEM_ALLOC_HOST_PTR。 在本地计算机和OpenCL设备上都可以工作和运行,但我感兴趣的是这是否是正确的映射方式,以及它是否应该适用于所有OpenCL设备。 我对USE_HOST_PTR示例特别不确定。

我只对缓冲区/地图特定操作感兴趣。 我知道我应该做错误检查等等。

CL_MEM_ALLOC_HOST_PTR:

// pointer to hold the result int * host_ptr = malloc(size * sizeof(int)); d_mem = clCreateBuffer(context,CL_MEM_READ_WRITE|CL_MEM_ALLOC_HOST_PTR, size*sizeof(cl_int), NULL, &ret); int * map_ptr = clEnqueueMapBuffer(command_queue,d_mem,CL_TRUE,CL_MAP_WRITE, 0,size*sizeof(int),0,NULL,NULL,&ret); // initialize data for (i=0; i<size;i++) { map_ptr[i] = i; } ret = clEnqueueUnmapMemObject(command_queue,d_mem,map_ptr,0,NULL,NULL); //Set OpenCL Kernel Parameters ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&d_mem); size_t global_work[1] = { size }; //Execute OpenCL Kernel ret = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, global_work, NULL, 0, 0, NULL); map_ptr = clEnqueueMapBuffer(command_queue,d_mem,CL_TRUE,CL_MAP_READ, 0,size*sizeof(int),0,NULL,NULL,&ret); // copy the data to result array for (i=0; i<size;i++){ host_ptr[i] = map_ptr[i]; } ret = clEnqueueUnmapMemObject(command_queue,d_mem,map_ptr,0,NULL,NULL); // cl finish etc 

CL_MEM_USE_HOST_PTR:

 // pointer to hold the result int * host_ptr = malloc(size * sizeof(int)); int i; for(i=0; i<size;i++) { host_ptr[i] = i; } d_mem = clCreateBuffer(context,CL_MEM_READ_WRITE|CL_MEM_USE_HOST_PTR, size*sizeof(cl_int), host_ptr, &ret); // No need to map or unmap here, as we use the HOST_PTR the original data // is already initialized into the buffer? //Set OpenCL Kernel Parameters ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&d_mem); size_t global_work[1] = { size }; //Execute OpenCL Kernel ret = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, global_work, NULL, 0, 0, NULL); // this returns the host_ptr so need need to save it (I assume it always will?) // although we do need to call the map function // to ensure the data is copied back. // There's no need to manually copy it back into host_ptr // as it uses this by default clEnqueueMapBuffer(command_queue,d_mem,CL_TRUE,CL_MAP_READ, 0,size*sizeof(int),0,NULL,NULL,&ret); ret = clEnqueueUnmapMemObject(command_queue,d_mem,map_ptr,0,NULL,NULL); // cl finish, cleanup etc 

如果使用CL_MEM_ALLOC_HOST_PTR,则OpenCL的底层实现可能会使用页锁定内存

这意味着页面无法交换到磁盘,主机和设备内存之间的传输将完成DMA样式而不会浪费CPU周期。 因此,在这种情况下,CL_MEM_ALLOC_HOST_PTR将是最佳解决方案。

nVidia具有页面锁定( 固定 )内存function,他们也应该在OpenCL实现中使用它。 对于AMD来说,不确定他们是否也这样做。 点击此处了解更多详情。

使用CL_MEM_USE_HOST_PTR只会让程序员的生活更轻松,所以在不太可能的情况下,当硬件无法使用页面锁定内存时,您可以使用此选项。