OpenCL2.0特性之SVM

来源:互联网 发布:知乎 环氧树脂固化剂 编辑:程序博客网 时间:2024/05/21 17:09

  在OpenCL2.0中,增加了SVM(shared virtual memory)的特性。在开始讲解SVM之前,我们先用图片来看下OpenCL1.2中主机与设备端的地址空间:


                                                 图1 OpenCL1.2中主机与设备端地址空间

        从图1可以看到,主机与设备具有不同的地址空间,各自需要对各自的内存进行管理。彼此之间不能直接访问对方的地址空间。所以,两者之间数据需要通信的话,只能把数据在主机与设备间来回拷贝,或者把设备端地址空间map /unmap到主机端。对于这样一种模式下,如果我们要想在设备端处理主机端的链表、树之类的数据。我们只能鞭长莫及!对于异构平台,我们就真的没办法愉快地处理链表之类的数据么?技术是发展的,有需求就必有技术来解决!

     从CUDA6以后,GPU与CPU之间支持统一寻址(Unified Memory)  ,GPU与CPU间可以直接访问彼此的地址空间,不需要我们人为的数据拷贝。这给异构计算又带入了一个新的高度,我们可以处理链表数据啦!既然CUDA都开始支持了,OpenCL也不能落后呀。在OpenCL2.0中,增加了共享虚拟内存(shared virtual memory),我们还是以一张图片来形象的描述:


                                              图2 OpenCL2.0中主机与设备端地址空间

      从图2可以看到,图1中原来两个彼此不相交的地址空间现在有个公共交集,这个公共交集就是SVM.。对于SVM的地址空间,主机和设备都可以直接访问,妈妈再也不用担心异构平台的数据访问方式了!

说完了SVM的意义,我们来聊聊SVM的具体细节。

        对于SVM的创建,OpenCL2.0中有两种方式,一种缓冲分配(buffer allocation),另一种是系统分配(System allocation):

        1、所谓缓冲分配,就是我们使用OpenCL API函数clSVMAlloc来分配,然后使用clSetKernelArgSVMPointer把分配的SVM作为内核参数传入

         2、所谓系统分配,就是在主机端,我们可以使用malloc,new之类的系统分配内存函数来分配空间,然后使用clSetKernelArgSVMPointer把分配的SVM作为内核参数传入。

        对于SVM的类型,OpenCL2.0也是有两种类型:一种是粗粒度;另一种是细粒度:

        1、粗粒度SVM:共享发生在OpenCL缓冲内存对象区域粒度。在同步点强制内存一致性,使用map/unmap命令来更新主机与设备间的数据。粗粒度的SVM与OpenCL1.2中使用缓冲对象类似,不过唯一不同的是:我们不需要来回拷贝数据,设备与主机可以直接访问对方的数据,这才是重点!

       2、所谓细粒度SVM:共享发生在OpenCL缓冲对象单个的加载/存储粒度。内存一致性在同步点得到保证。

        好,结合SVM分配方式和SVM类型,可以把OpenCL2.0中的SVM分为:粗粒度缓冲SVM,细粒度缓冲SVM,细粒度系统SVM。(木有粗粒度系统SVM)。对于你的OpenCL设备(请确保你的设备支持OpenCL2.0),到底支持上述三种的哪三种呢?我们可以通过如下代码查询:

         

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1.         cl_device_svm_capabilities svm;  
  2. clGetDeviceInfo(*device,CL_DEVICE_SVM_CAPABILITIES,sizeof(svm),&svm,NULL);  
  3. if(svm&CL_DEVICE_SVM_FINE_GRAIN_SYSTEM)  
  4.     printf("CL_DEVICE_SVM_FINE_GRAIN_SYSTEM\n");  
  5. if(svm&CL_DEVICE_SVM_FINE_GRAIN_BUFFER)  
  6.     printf("CL_DEVICE_SVM_FINE_GRAIN_BUFFER\n");  
  7. if(svm&CL_DEVICE_SVM_COARSE_GRAIN_BUFFER)  
  8.     printf("CL_DEVICE_SVM_COARSE_GRAIN_BUFFER\n");  
       在我的AMD A10-7400 Radeon R6平台上,当设备为CL_DEVICE_TYPE_GPU时,输出为:

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. CL_DEVICE_SVM_FINE_GRAIN_BUFFER  
  2. CL_DEVICE_SVM_COARSE_GRAIN_BUFFER  
      对于细粒度系统SVM,AMD当前是不支持的。

      粗粒度缓冲SVM和细粒度缓冲SVM大致用法,如下表格所示

Coarse-grained SVM
(Map/Unmap is requred)fine-grained SVM buffer
[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. float* p = (float*)clSVMAlloc(…);  
  2.   
  3. clEnqueueSVMMap(…,  
  4.     CL_TRUE,  // block until map is done  
  5.     p, …);  
  6.   
  7.   
  8. // Initialize SVM buffer  
  9. p[i] = …;  
  10.   
  11. clEnqueueSVMUnmap(…, p, …);  
  12.   
  13. clEnqueueNDRange(…);  
  14.   
  15. clEnqueueSVMMap(…,  
  16.     CL_TRUE,  // block until map is done  
  17.     p, …);  
  18.   
  19. // Read the data produced by the kernel  
  20. … = p[i];  
  21.   
  22. clEnqueueSVMUnmap(…, p, …);  
[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. float* p = (float*)clSVMAlloc(…);  
  2.   
  3.   
  4.   
  5.   
  6.   
  7.   
  8.   
  9. // Initialize SVM buffer  
  10. p[i] = …;  
  11.   
  12.   
  13.   
  14. clEnqueueNDRange(…);  
  15.   
  16. clFinish(…);  
  17.   
  18.   
  19.   
  20.   
  21. // Read the data produced by the kernel  
  22. … = p[i];   


OpenCL2.0 SVM的讲解,就到这吧!

 ps:最后唠叨一句:对于SVM,方便了我们码农编程,从硬件上来说,OpenCL设备与主机不一定是共享物理内存的。

     

0 0
原创粉丝点击