1

clEnqueueCopyBufferRect がどのように機能しているかを理解する必要があります。たとえば、原点 (1,1) を持つ 4x4 領域 (int 配列とします) から 3x3 領域をコピーする必要があります。2 つの提案があります。

  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 に答える