我需要了解 clEnqueueCopyBufferRect 是如何工作的。例如,我需要从具有原点 (1,1) 的 4x4 区域(让它成为 int 数组)复制 3x3 区域。我有两个建议:
它只是复制大小与矩形 3x3 区域大小匹配的线性区域,因此结果是:
1 1 1 1 0 0 0 0 1 1 1 1 -> 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0
或者它复制矩形区域,结果是:
1 1 1 1 0 0 0 0 1 1 1 1 -> 0 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 0 1 1 1
为了检查这一点,我使用了下一个示例代码:
int main(int argc, char * argv[])
{
std::vector<Platform> platforms;
Platform::get(&platforms);
cl::Platform platform = platforms[0];
cl_context_properties cps[3] = {CL_CONTEXT_PLATFORM, (cl_context_properties)platform(), 0};
cl::Context context(CL_DEVICE_TYPE_GPU,cps);
std::string kr_str = "__kernel void StepKernel(__global int* in) { in[get_global_id(1)*4 + get_global_id(0)] = 1;}";
Program program=cl::Program(
context,
cl::Program::Sources(
1,
std::make_pair(kr_str.c_str(),kr_str.length()+1)
)
);
std::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>();
std::vector<cl::Device> device(1,devices[0]);
program.build(device);
cl::Kernel kernel = cl::Kernel(program, "StepKernel");
cl::CommandQueue queue(
context,
device[0],
CL_NONE
);
cl::Buffer in_buffer_on_device(
context,
CL_MEM_READ_WRITE,
16*sizeof(int)
);
cl::Buffer out_buffer_on_host(
context,
CL_MEM_READ_WRITE|CL_MEM_ALLOC_HOST_PTR,
16*sizeof(int)
);
void *ptr_on_host =
queue.enqueueMapBuffer(
out_buffer_on_host,
CL_BLOCKING,
CL_MAP_WRITE|CL_MAP_READ,
0, 16*sizeof(int),
NULL, NULL
);
for(int k = 0; k < 4; k++)
for(int i = 0; i < 4; i++)
static_cast<int*>(ptr_on_host)[k*4 + i] = 0;
cl::size_t<3> origin, region;
origin[0]=0; origin[1]=0; origin[2]=0;
region[0]=4*sizeof(int); region[1]=4; region[2]=1;
Event evt;
queue.enqueueCopyBufferRect(
out_buffer_on_host,
in_buffer_on_device,
origin, origin, region,
sizeof(int)*4,sizeof(int)*4*4,sizeof(int)*4,sizeof(int)*4*4,
NULL,
&evt
);
evt.wait();
kernel.setArg(0,in_buffer_on_device);
queue.enqueueNDRangeKernel(
kernel,
cl::NDRange( 0, 0),
cl::NDRange( 4, 4),
cl::NullRange,
NULL,
&evt
);
evt.wait();
origin[0]=1*sizeof(int); origin[1]=1; origin[2]=0;
region[0]=3*sizeof(int); region[1]=3; region[2]=1;
queue.enqueueCopyBufferRect(
in_buffer_on_device,
out_buffer_on_host,
origin, origin, region,
sizeof(int)*4,sizeof(int)*4*4,sizeof(int)*4,sizeof(int)*4*4,
NULL,
&evt
);
evt.wait();
for(int k = 0; k < 4; k++)
{
for(int i = 0; i < 4; i++)
{
std::cout << static_cast<int*>(ptr_on_host)[k*4 + i]<< "\t";
}
std::cout << std::endl;
}
return 0;
}
输出是:
0 0 0 0
0 1 1 1
1 1 1 1
1 1 0 0
所以,如果我没有犯任何错误,CL 会复制线性区域。所以这样的行为对我来说毫无用处。