1

我需要了解 clEnqueueCopyBufferRect 是如何工作的。例如,我需要从具有原点 (1,1) 的 4x4 区域(让它成为 int 数组)复制 3x3 区域。我有两个建议:

  1. 它只是复制大小与矩形 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
    
  2. 或者它复制矩形区域,结果是:

    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 会复制线性区域。所以这样的行为对我来说毫无用处。

4

1 回答 1

0

它复制矩形区域。否则它作为 API 将毫无用处。

于 2013-01-30T07:44:25.093 回答