Chinaunix首页 | 论坛 | 博客
  • 博客访问: 743915
  • 博文数量: 769
  • 博客积分: 6000
  • 博客等级: 准将
  • 技术积分: 4985
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-15 16:37
文章分类

全部博文(769)

文章存档

2011年(1)

2008年(768)

我的朋友

分类:

2008-10-15 16:40:36

    Brook是标准ANSI C语言的扩展,它是一种为人们所熟悉的高效的语言,它集成了数据并行计算和算术计算集中这两个特点。
    通用的计算模型,也就是所谓的流(Stream),同传统的常规语言相比,有以下两个主要的优点:
    1.数据并行:允许编程者指定如何在不同的数据上并行地执行相同的操作。
    2.算术计算集中:鼓励编程者指定数据上的操作,以达到全局的通信最小而局部的计算最大!
    更多的关于Brook的内容可以在Merrimac web site 找到,里面包括了这种语言的完整的说明。Brookgpu为了在GPU上使用,它实现了Brook规范的一个子集。一个Brook 程序中包含合法的C代码和声明流(streams)的句法扩展以及叫做kernels的函数。

    流(Streams)
    流是一个新的数据类型的扩展,代表了一系列能够被并行处理的数据。Streams的声明规则和数组很像,都是使用尖括号进行声明的。声明一个流的例子如下所示:
    float s <10, 10>;
    上面声明了一个2维的浮点类型的流。每个流都是由流元素组成的。在上面的例子中,s是一个包含了100个浮点类型流元素的流。流的形状就是指流的维数。在这个例子中,流的形状是10×10。流是用列优先的方式来进行描述的,同C语言中的数组类似。因此,形状为<100>的流与形状为< 1,100>和<1,1,100>的流是等同的。
    尽管同C数组很类似,但Brookgpu中的流同C语言中的数组有以下的区别:
    1. 在kernels函数外不允许通过下标来获得流元素(例如 s[3][2])。
    2. 不允许对流进行静态的初始化,例如:
    float s<100>={1.0f,2.0f,....}是不允许的。
    3. 流必须是局部变量(堆栈)。

    4. 流只能在核心(kernel)函数中被读写或者是通过特殊的运算符从普通的指针和versa 获得数据。
    streamRead(s,data_s);
    /*用*data_s处的数据对流stream s<>进行赋值*/
    streamWrite(s,data_s);
    /*用流s<>的数据对*data_s进行赋值*/
    尽管这个操作还可能通过编译器进行进一步的优化,但是它向流中进行拷贝已经是十分高效了。
    对于GPU编译过的代码,流对应于组织内存(texture memory)的区域。编译器能进行代码流分析来更好地决定什么时候什么地点来分配组织内存(texture memory),或者完全消除流变量需要暂时的需要。为了方便起见,brook也扩展C来包括float2,float3和float4作为基本的数据类型。这些类型同C语言中用typedef 的结构(strUCts)是等价的。例如:
    typedef stuct {
    float x;
    float y;
    float z;
    float w;
    } float4;
    另外,这些数据类型能够通过使用构造函数的语法来构造:
    float4 a (0.2f,1.0f,3.2f,1.0f); // x=0.2f,y=1.0f ......
    核心(kernels)
    核心是在流上操作的特殊函数,是应用到每个输入流元素的一种并行函数。在一系列的输入流上调用一个核心函数就在每个流元素上实施了隐含的循环,即对每一个流元素调用核心体。通过GPU带有的核心函数,流被输入进视频器,核心函数被编译成由其“渲染”的分段程序。除了在声明核心时,它的前面要加上关键字 kernel,核心的定义和函数的定义非常的相似,返回类型通常都是void,并且其中的一个流参数要标记类型限定语'out'。全局内存空间和静态变量在kernels里无法被访问。一个kernel声明的例子如下所示:
    kernel void k (float s<>,float3 f, float3 f, float a[10][10], out float o<>)
    在这个例子中,输入流s的每一个元素都要调用kernel k的核心体。变量s在kernel体的内部的类型是float,为了每次隐含的调用,s被初始化为一个不同的元素。变量f是kernel中的一个常数,它在每次迭代中保持同一个值。在kernels内部,对输入流或是常数参数进行写操作都是不允许的。
    变量a是一个二维数组,它可以通过标准C语言访问数组的方法来访问。a的维数并不需要被指定,然而如果指定了数组的维数,编译器可以更快地产生代码。每一个流都会以数组形式输入到一个核心(kernel)里面。
    变量o是一个输出流。输出流是一个只写的参数,它的值由kernel函数体来进行赋值。在kernel体的内部,变量o的类型也是float。s的每一个元素都隐含地执行kernel体,产生输出流o的元素。注意到kernel的原型和函数体都受限于C和支持的cg/HLSL的子集。它们包括向量流类型,矩阵类型和标准的库函数。
    想获得更多的信息,请参照CG语言规范,网址是:
    _cg_toolkit.html">http://developer.nvidia.com/object/_cg_toolkit.html
   
    也可以参照HLSL文档,网址是:
    - us/directx9_c/directx/graphics/reference/Shaders/HighLevelShaderLanguage.asp
    调用一个kernel函数同调用任何C函数类似。
    kernel void k(float s<>, float3 f, float a[10][10], out float o<>);
    float a<100>;

[1]   

【责编:landy】

--------------------next---------------------

阅读(686) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~