欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

OpenCL2.0特性之SVM

发布时间:2025/7/25 编程问答 44 豆豆
生活随笔 收集整理的这篇文章主要介绍了 OpenCL2.0特性之SVM 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

from: http://blog.csdn.net/hdanbang/article/details/50198415

在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 plaincopy
  •         cl_device_svm_capabilities svm;  
  • clGetDeviceInfo(*device,CL_DEVICE_SVM_CAPABILITIES,sizeof(svm),&svm,NULL);  
  • if(svm&CL_DEVICE_SVM_FINE_GRAIN_SYSTEM)  
  •     printf("CL_DEVICE_SVM_FINE_GRAIN_SYSTEM\n");  
  • if(svm&CL_DEVICE_SVM_FINE_GRAIN_BUFFER)  
  •     printf("CL_DEVICE_SVM_FINE_GRAIN_BUFFER\n");  
  • if(svm&CL_DEVICE_SVM_COARSE_GRAIN_BUFFER)  
  •     printf("CL_DEVICE_SVM_COARSE_GRAIN_BUFFER\n");  
  •        在我的AMD A10-7400 Radeon R6平台上,当设备为CL_DEVICE_TYPE_GPU时,输出为:

    [html] view plaincopy
  • CL_DEVICE_SVM_FINE_GRAIN_BUFFER  
  • CL_DEVICE_SVM_COARSE_GRAIN_BUFFER  
  •       对于细粒度系统SVM,AMD当前是不支持的。

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

    Coarse-grained SVM
    (Map/Unmap is requred)fine-grained SVM buffer
    [cpp] view plaincopy
  • float* p = (float*)clSVMAlloc(…);  
  •   
  • clEnqueueSVMMap(…,  
  •     CL_TRUE,  // block until map is done  
  •     p, …);  
  •   
  •   
  • // Initialize SVM buffer  
  • p[i] = …;  
  •   
  • clEnqueueSVMUnmap(…, p, …);  
  •   
  • clEnqueueNDRange(…);  
  •   
  • clEnqueueSVMMap(…,  
  •     CL_TRUE,  // block until map is done  
  •     p, …);  
  •   
  • // Read the data produced by the kernel  
  • … = p[i];  
  •   
  • clEnqueueSVMUnmap(…, p, …);  
  • [cpp] view plaincopy
  • float* p = (float*)clSVMAlloc(…);  
  •   
  •   
  •   
  •   
  •   
  •   
  •   
  • // Initialize SVM buffer  
  • p[i] = …;  
  •   
  •   
  •   
  • clEnqueueNDRange(…);  
  •   
  • clFinish(…);  
  •   
  •   
  •   
  •   
  • // Read the data produced by the kernel  
  • … = p[i];   

  • 具体的SVM例子,请移步这里

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

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

    总结

    以上是生活随笔为你收集整理的OpenCL2.0特性之SVM的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。