opencl优化-Zero Copy

转自:https://www.cnblogs.com/willhua/tag/OpenCL/

有两种方式实现从主机到CL设备的数据传递,
第一种:

1 cl_mem input = clCreateBuffer(context,CL_MEM_READ_ONLY,sizeof(float) * DATA_SIZE, NULL, NULL);
2 clEnqueueWriteBuffer(command_queue, input, CL_TRUE, 0, sizeof(float) * DATA_SIZE, inputdata, 0, NULL, NULL);

第二种:

 1 cl_mem input = clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(float) * DATA_SIZE, inputdata, NULL); 

  • 这两种写法可以说是没啥区别,但是如过第二中写法中CL_MEM_COPY_HOST_PTR换成CL_MEM_USE_HOST_PTR,那么根据文档的说法,第二种并不会把主机的inputdata复制到设备,而仅仅是cache
  • 如果inputdata仅仅会初始化一次,那么使用第二种方法看起来更加便捷;但是如果对inputdata要进行多次更新,那么使用第一种的方式更好,可以调用clEnqueueWriteBuffer进行更新
  • 使用第一种可以在clEnqueueWriteBuffer中使用event来测量耗时
  • 第一种写法会先在主机创建一个second temporary buffer on the host,然后等到设置这个buffer到kernel的时候再把数据拷贝到设备上。这样,就可能会在一个短暂的时候,主机上有两份内存。如果buffer比较大,就会引发问题。而第二种方法则是立即把数据复制的设备,没有额外的临时内存分配。参考
  • 如果clcontext上绑定了多个device,那么使用第二种方法则会在每个device上都分配该buffer。如果只想对某个设备分配该buffer,那么就应该使用与device绑定了的clEnqueueWriteBuffer参考
  • 然而,在高通的优化指南中,这两种做法都不推荐。推荐使用Zero Copy的写法,其关键在于CL_MEM_ALLOC_HOST_PTR的应用
 1 // First set cl_mem_flags input in clCreateBuffer:
 2 cl_mem Buffer = clCreateBuffer(context,
 3     CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR,
 4     sizeof(cl_ushort) * size,
 5     NULL,
 6     &status);
 7 //Then use the map function to return a pointer to the host:
 8 cl_uchar *hostPtr = (cl_uchar *)clEnqueueMapBuffer(
 9     commandQueue,
10     Buffer,
11     CL_TRUE,
12     CL_MAP_WRITE,
13     0,
14     sizeof(cl_uchar) * size,
15     0, NULL, NULL, &status);
16 
17 //Host updates the buffer using the pointer hostPtr
18     memcpy(hostPtr, sizeof(cl_uchar) * size, datafromhost);
19     
20 //Unmapped the object
21 status = clEnqueueUnmapMemObject(
22     commandQueue,
23     Buffer,
24     (void *) hostPtr,
25     0, NULL, NULL);
26     
27 //The object can be used by OpenCL kernels

 

posted @ 2022-12-16 14:38  墨尔基阿德斯  阅读(259)  评论(0编辑  收藏  举报