zoukankan      html  css  js  c++  java
  • 【转载】opencl中设备内存

    地址空间限定符

    一般的内核代码中,里面的内核参数或声明变量时,都会有地址空间限定符
    地址空间限定符,地址空间限定符的主要作用是指出数据应该保存在哪个地方
    地址空间限定符有4个:

    全局内存:

    限定符:__global.保存一个设备中的数据,可读也可写,这意味着一个设备中的各个工作组、各个工作项是可以共享的,
    主机和设备都可以读写访问,当主机应用程序将缓存对象传输给设备,缓存数据是存放在全局/常数空间中,当主机从设备中
    读取缓存对象,数据将来自设备的全局内存。全局/常数内存往往是一个opencl兼容设备上最大的内存区域,但是访问速度最慢。从这里可以看出
    全局区域主要用于主机和设备之间进行数据传输。

    常数内存:

    限定符:__constant.和全局内存相似,但是只可以读。其在使用前必须要初始化

    局部内存:

    限定符:__local.保存工作组中工作项的数据,这意味着,局部内存在同一个工作组内存是可以共享的.
    这种类型的数据只会针对处理内核的各个工作组分配一次,然后在工作组处理结束之后释放内存

    私有内存:

    限定符:__private。只在一个工作项中有效,需要注意的是,如果内核参数或者内核程序中的变量声明没有加限定符,
    那么他将被保存在私有内存中。如果指针变量没有加限定符,他就会被设置指向私有内存。但image2d_t和image3d_t型指针会一直指向全局内存

    限定符所限定的对象:

    __global:可以限定所有的内核参数,并不仅仅是指针参数。除了参数之外,还可以限定内核之中所声明的指针变量。

    __local:可以用于限定内核参数以及内核中声明的变量,但需要特别注意的是,不管是主机还是设备,都不能够对其进行直接初始化
    如,下面会报错:

    __local float x = 4.0;
    这样会报错,解决办法是:
    __local float x;
    x = 4.0;

    __private:可以限定可以用于限定内核参数以及所有非内涵函数的参数和变量。
    主机配置局部内存

    主机与设别之间的数据通信是通过全局内存实现的,这意味着主机不能读写局部、私有内存。但是主机可以配置局部、私有内存。
    比如,主机可以告诉设备如何为内核参数分配局部内存。
    为了编程配置整个过程,需要将clSetKernelArg函数的最后一个参数设为NULL。如下面由主机执行的代码,用来配置局部参数,
    分配足够保存16个浮点数的内存空间:

    slSetKernelArg(kernel,0,16*sizeof(float),NULL);

    对应的内核函数:

    __kernel void proc_data(__local float* nums,...)
    {

    }

    和全局内存相似,局部内存的访问速度更快,因此,最好是先将数据从全局内存读取到局部内存中,然后在局部内存中进行处理。在工作项处理
    完局部数据之后,再将结果写到全局内存中,再传输回主机。

    主机配置私有内存
    私有内存的访问速度最快,但是内存空间最小。
    和局部内存不一样,内核参数的私有数据可以由主机来进行初始化。为了配置私有内存数据,主机需要将clSetKernelArg函数
    最后一个参数设定为基本数据类型,如int*、float*,char*等,但内核函数中对应的私有内核参数必须是基本数据类型,对应为int、float、char等。
    下面的例子是:内核需要每个工作项都能够访问int变量num_iteration所在的地址空间,并且希望其初始化值为4,对应的主机程序:

    int num_iteration = 4;
    clSetKernelArg(kernel,0,sizeof(num_iteration),&num_iteration);
    对应的内核函数:

    __kernel void proc_data(int num_iteration,...)
    {

    }

    该内核函数参数没有限定符,因此默认是私有内存,那么每一个工作项都会有一个自己的副本
    该参数和以前的参数不一样,num_iteration不是一个指针。私有内核参数并不是引用,它们必须是像int和float那样的基本数据类型

    全局/常数数据只能通过引用传递的方式给内核,而私有数据是值传递的方式

    私有内核参数必须是基本数据类型,但是不一定需要是标量,也可以是向量。例如,你想将四个float型数据发送给内核,然后
    再将float型数放到设备的私有地址空间中,以便快速访问,在主机应用程序中。可以加入下面的代码来实现这个目的:

    float nums[4] = {0.0f,1.0f,2.0f,3.0f};
    clSetKernelArg(kernel,0,sizeof(nums),nums);
    内核不能以4元素数组的形式访问私有数据,因为私有参数不能是指针,但是数据可以以float4型向量的形式来访问:

    __kernel void proc_data(float4 vaues,...)
    {
    ...
    }

    简单总结:

    如果在调用clSetKernelArg函数时,指针指向内存对象(cl_mem),那么对应的内核参数必须是声明为__global或__constant类型的指针。

    如果调用clSetKernelArg函数时,指针被声明NULL,对应的内核参数必须被声明为__local类型的指针,且主机程序能够做的只是告诉设备如何为内核参数分配局部内存

    如果调用clSetKernelArg函数时,指针指向的是基本数据类型,内核参数就不会是指针,也不需要有任何地址限定符。

  • 相关阅读:
    ActiveX在.NET 2005中的实现(三)
    SharePoint学习研究资源
    配置Excel Service的Excel Web Access 功能及应用
    SkyDrive 与 Hotmail 的 Office Web Apps
    ActiveX在.NET 2005中的实现(二)
    Sharepoint设置SMTP邮件发送服务器(使用中继服务器)
    SharePoint2010新功能
    Analysis自动处理
    NBear V3
    Server数据推送,长连接
  • 原文地址:https://www.cnblogs.com/mod109/p/6385491.html
Copyright © 2011-2022 走看看