0

取自 OpenCL by Action

下面的代码实现了如图所示的目标。它创建两个缓冲区对象,并使用 clEnqueueCopyBuffer 将缓冲区 1 的内容复制到缓冲区 2。

然后 clEnqueueMapBuffer 将 Buffer 2 的内容映射到主机内存, memcpy 将映射的内存传输到一个数组。

在此处输入图像描述

我的问题是如果我不在代码中编写以下行,我的代码是否仍然有效:

    err = clSetKernelArg(kernel, 0, sizeof(cl_mem),  
                 &buffer_one);                     
    err |= clSetKernelArg(kernel, 1, sizeof(cl_mem), 
                  &buffer_two);              
    queue = clCreateCommandQueue(context, device, 0, &err);
    err = clEnqueueTask(queue, kernel, 0, NULL, NULL);     

内核是空白的,它什么也没做。设置内核参数和入队任务需要什么?

...
float data_one[100], data_two[100], result_array[100];
cl_mem buffer_one, buffer_two;
void* mapped_memory;
...

 buffer_one = clCreateBuffer(context,           
  CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR,             
  sizeof(data_one), data_one, &err);       
 buffer_two = clCreateBuffer(context,                  
  CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR,       
  sizeof(data_two), data_two, &err);  



  err = clSetKernelArg(kernel, 0, sizeof(cl_mem),  
                 &buffer_one);                     
  err |= clSetKernelArg(kernel, 1, sizeof(cl_mem), 
                  &buffer_two);              
 queue = clCreateCommandQueue(context, device, 0, &err);
 err = clEnqueueTask(queue, kernel, 0, NULL, NULL);     



 err = clEnqueueCopyBuffer(queue, buffer_one,  
  buffer_two, 0, 0, sizeof(data_one),           
  0, NULL, NULL);            



  mapped_memory = clEnqueueMapBuffer(queue, 
  buffer_two, CL_TRUE, CL_MAP_READ, 0,            
  sizeof(data_two), 0, NULL, NULL, &err);
  memcpy(result_array, mapped_memory, sizeof(data_two));       
  err = clEnqueueUnmapMemObject(queue, buffer_two, 
  mapped_memory, 0, NULL, NULL);                  
  }

...

4

1 回答 1

0

我相信调用 enqueueTask 的目的是确保数据实际上驻留在设备上。有可能在使用该CL_MEM_COPY_HOST_PTR标志时,内存仍保留在主机端,直到内核需要它为止。因此,将任务入队可确保将内存带到设备中。这也可能发生在某些设备上,但不会发生在其他设备上。

您可以通过检测您的代码并测量运行任务所花费的时间来测试这个理论,无论是任务有参数还是没有参数。如果任务需要更长的时间进行争论,那么这很可能是正在发生的事情。

于 2012-10-09T16:58:04.353 回答