我创建了一个具有CL_MEM_READ_WRITE和CL_MEM_ALLOC_HOST_PTR属性的缓冲区。我已将此缓冲区排入GPU内核。 GPU内核处理给定的输入并填充这些缓冲区。在此过程中,CPU会等待。我通过使用子缓冲区将缓冲区分成三个统一的部分来修改此设计。现在GPU填充一个子缓冲区后,CPU就可以开始处理了。这减少了CPU等待一个子缓冲区而不是一个全帧处理。
我面临的问题是,子缓冲区和缓冲区的映射指针(cpu侧指针)很奇怪。第一个子缓冲区和缓冲区的映射指针是相同的。这没关系。但是第二个子缓冲区的映射指针不等于第二个子缓冲区的缓冲区+偏移量的映射指针。我在集成GPU模型(英特尔高清显卡4000)上试过这个。它工作正常。但是,当我在专用显卡设备(nvidia zotac)上运行时,我正面临着这个问题。你以前遇到过这种情况吗?您能否提供一些指示,指出解决此问题的方法。
typedef struct opencl_buffer {
cl_mem opencl_mem;
void *mapped_pointer;
int size;
}opencl_buffer;
// alloc gpu output buffers
opencl->opencl_mem = clCreateBuffer(
opencl->context, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR,
3 * alloc_size, NULL, &status);
if (status != CL_SUCCESS)
goto fail;
// create output sub buffers
for (sub_idx = 0; sub_idx < 3; ++sub_idx) {
cl_buffer_region sf_region;
SubFrameInfo subframe;
sf_region.origin = alloc_size * sub_idx;
sf_region.size = alloc_size;
opencl->gpu_output_sub_buf[sub_idx].size = sf_region.size;
opencl->gpu_output_sub_buf[sub_idx].opencl_mem =
clCreateSubBuffer(opencl->opencl_mem,
CL_MEM_READ_WRITE,
CL_BUFFER_CREATE_TYPE_REGION,
&sf_region, &status);
if (status != CL_SUCCESS)
goto fail;
}
现在,当我映射gpu_output_sub_buf [0] .opencl_mem和gpu_output_sub_buf [1] .opencl_mem时,CPU端指针之间的差异应该是alloc_size(假设为char指针)。这恰好是英特尔高清显卡的情况。但是Nvidia平台正在提供不同的结果。
答案 0 :(得分:2)
没有基于规范的原因,映射的子缓冲区应该位于与映射的主缓冲区(或与其对齐的映射的子缓冲区)的已知偏移量的地址处。映射仅创建可以使用的一系列主机内存,然后取消映射以将其恢复到设备上。它不必每次都在同一个地址。
当然,OpenCL 2.0 SVM会改变这一切,但你并没有说你正在使用SVM,而且NVIDIA今天也不支持OpenCL 2.0。