clCreateBuffer中cl_mem_flags参数解释

  • 设备与主机端的通信

    使用clCreateBuffer分配好内存,可以使用主机上已经存在的内容将其进行初始化,也可以先创建内存,再通过clEnqueueWriteBuffer,写数据,或者通过clEnqueueMapBuffer,将设备上的数据映射到主机端进行修改,修改后需要解映射,最后将分配好的内存,通过参数设置clSetKernelArg给到设备,如果数据改变了,则可以使用clEnqueueReadBuffer来读取数据,或者使用clEnqueueMapBuffer将内存映射到主机端进行访问,需要注意的是,在主机端对数据修改后,需要unmap,这样,设备端再次访问该数据的时候,就会是修改后的数据,否则访问未经解映射的内存,可能会读到预料不到的结果

clCreateBuffer函数用来给缓存对象分配内存,创建的内存可以是global、local、private,具体看kernel中怎么样声明限定符。 
这里的buffer概念是用于kernel函数计算的,只有这里分配的内存可以用于kernel函数执行,其函数签名如下:

cl_memclCreateBuffer ( cl_context context, 
                       cl_mem_flags flags, 
                       size_t size, 
                       void *host_ptr, 
                       cl_int *errcode_ret) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

cl_mem_flags参数可选项如下: 
前面3个参数主要是限制设备在分配的内存上的可访问性

  • 1 CL_MEM_READ_WRITE:

    设备可以读写,host_ptr可为空,这表明该参数不需要初始化

  • 2 CL_MEM_WRITE_ONLY:

    设备只写,host_ptr可为空,表明不需要初始化

  • 3 CL_MEM_READ_ONLY:

    设备只读,不能为空 
    下面的3个参数控制内存分配

  • 4 CL_MEM_USE_HOST_PTR:

    目的:在设备端处理缓存对象,并将缓存对象返回给主机,host_ptr指针不能为空(CL_MEM_USE_HOST_PTR优先采用在CPU端分配内存空间,让GPU端有访问权限,如果硬件不支持这种方式的话,则在GPU端开辟一块缓存,存储host_ptr里的内容) 
    特点是主机和设备端都可以访问, 
    类似于将主机上的内存块映射到设备上供设备使用,虽然是同一块内存,但是有可能在设备上对该 
    内存操作了,在主机上访问的结果不正确,因此有可能需要对数据进行同步

  • 5 CL_MEM_COPY_HOST_PTR:

    目的:在设备端处理数据,也不需要将数据返回给主机 
    在设备端分配内存,并将hsot_ptr指针指向的内存,拷贝size大小的数据到设备内存上去, 
    host_ptr不能为空,由于是直接拷贝,因此在设备端对数据进行修改后,主机端不能够获取相应数据

  • 6 CL_MEM_ALLOC_HOST_PTR:

    目的:在主机可访问的地方分配内存,在设备端对数据进行初始化 
    在该标志位下,opencl可能直接在固定内存上分配内存(而在固定内存上操作系统使用DMA进行数据传输 )

CL_MEM_ALLOC_HOST_PTR和CL_MEM_USE_HOST_PTR不能够同时使用

CL_MEM_ALLOC_HOST_PTR必须和CL_MEM_COPY_HOST_PTR一起使用,不能单独使用,他们联合起来可用于初始化主机可访问的内存块(如PCIe:新的总线和接口标准,主要优势是数据传输速率高), 
这可能比使用CL_MEM_USE_HOST_PTR要速度快

clCreateBuffer分配的内存所指向的连续数据位置,在内核执行期间,内核都能够访问

  • 最后,总结一下:

cl_mem_flags参数的前三个使用来限制设备的读写权限的,而不是主机端读写权限 
后三个参数中,如果主机端的数据直接传输后不需要再读取结果,就使用CL_MEM_COPY_HOST_PTR, 
如果数据需要再读取回来,则可以使用CL_MEM_ALLOC_HOST_PTR和CL_MEM_COPY_HOST_PTR一起或者CL_MEM_USE_HOST_PTR

  • 设备与主机端的通信

    使用clCreateBuffer分配好内存,可以使用主机上已经存在的内容将其进行初始化,也可以先创建内存,再通过clEnqueueWriteBuffer,写数据,或者通过clEnqueueMapBuffer,将设备上的数据映射到主机端进行修改,修改后需要解映射,最后将分配好的内存,通过参数设置clSetKernelArg给到设备,如果数据改变了,则可以使用clEnqueueReadBuffer来读取数据,或者使用clEnqueueMapBuffer将内存映射到主机端进行访问,需要注意的是,在主机端对数据修改后,需要unmap,这样,设备端再次访问该数据的时候,就会是修改后的数据,否则访问未经解映射的内存,可能会读到预料不到的结果

clCreateBuffer函数用来给缓存对象分配内存,创建的内存可以是global、local、private,具体看kernel中怎么样声明限定符。 
这里的buffer概念是用于kernel函数计算的,只有这里分配的内存可以用于kernel函数执行,其函数签名如下:

cl_memclCreateBuffer ( cl_context context, 
                       cl_mem_flags flags, 
                       size_t size, 
                       void *host_ptr, 
                       cl_int *errcode_ret) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

cl_mem_flags参数可选项如下: 
前面3个参数主要是限制设备在分配的内存上的可访问性

  • 1 CL_MEM_READ_WRITE:

    设备可以读写,host_ptr可为空,这表明该参数不需要初始化

  • 2 CL_MEM_WRITE_ONLY:

    设备只写,host_ptr可为空,表明不需要初始化

  • 3 CL_MEM_READ_ONLY:

    设备只读,不能为空 
    下面的3个参数控制内存分配

  • 4 CL_MEM_USE_HOST_PTR:

    目的:在设备端处理缓存对象,并将缓存对象返回给主机,host_ptr指针不能为空(CL_MEM_USE_HOST_PTR优先采用在CPU端分配内存空间,让GPU端有访问权限,如果硬件不支持这种方式的话,则在GPU端开辟一块缓存,存储host_ptr里的内容) 
    特点是主机和设备端都可以访问, 
    类似于将主机上的内存块映射到设备上供设备使用,虽然是同一块内存,但是有可能在设备上对该 
    内存操作了,在主机上访问的结果不正确,因此有可能需要对数据进行同步

  • 5 CL_MEM_COPY_HOST_PTR:

    目的:在设备端处理数据,也不需要将数据返回给主机 
    在设备端分配内存,并将hsot_ptr指针指向的内存,拷贝size大小的数据到设备内存上去, 
    host_ptr不能为空,由于是直接拷贝,因此在设备端对数据进行修改后,主机端不能够获取相应数据

  • 6 CL_MEM_ALLOC_HOST_PTR:

    目的:在主机可访问的地方分配内存,在设备端对数据进行初始化 
    在该标志位下,opencl可能直接在固定内存上分配内存(而在固定内存上操作系统使用DMA进行数据传输 )

CL_MEM_ALLOC_HOST_PTR和CL_MEM_USE_HOST_PTR不能够同时使用

CL_MEM_ALLOC_HOST_PTR必须和CL_MEM_COPY_HOST_PTR一起使用,不能单独使用,他们联合起来可用于初始化主机可访问的内存块(如PCIe:新的总线和接口标准,主要优势是数据传输速率高), 
这可能比使用CL_MEM_USE_HOST_PTR要速度快

clCreateBuffer分配的内存所指向的连续数据位置,在内核执行期间,内核都能够访问

  • 最后,总结一下:

cl_mem_flags参数的前三个使用来限制设备的读写权限的,而不是主机端读写权限 
后三个参数中,如果主机端的数据直接传输后不需要再读取结果,就使用CL_MEM_COPY_HOST_PTR, 
如果数据需要再读取回来,则可以使用CL_MEM_ALLOC_HOST_PTR和CL_MEM_COPY_HOST_PTR一起或者CL_MEM_USE_HOST_PTR

猜你喜欢

转载自blog.csdn.net/Tommy_wxie/article/details/77335957
cl