(接上篇)

由main函数开始,生成三个流接受输入矩阵(A和B)和输出矩阵(流一般用来表示矩阵)。然后三块内存缓冲区开辟出来(input_A,input_B和

input_C)接着streamRead()函数将数据从input_A复制到流A,input_B到流B。

simple_matmult( (float) Width, A, B, C) 这一行将Width、输入流A、B和输出流C等参数传递给kernel函数,同时也触发了kernel函数在流处理器上的执行。在简单的矩阵乘法操作中,kernel函数从一个矩阵读入一行向量,从另一个矩阵读入一列向量,将二者点乘写入结果。在上面的例子中,kernel函数遍历输出流的每个数据的位置。总结如下:

1.循环遍历矩阵A的行;

2.循环遍历矩阵B的列;

3.每次从每个矩阵取出一个值;

4.乘法运算得到结果

这里kernel利用了一个特性就是向量数据类型(float2和float4)。Brook+支持最多四个元素的数据类型。(注:即最多四个分量的向量)元素可以通过任何结合方式被访问。这也就是所谓的混合(swizzling)。

这里kernel的输入流和前面的sum kernel的流稍有不同。这里,流是用方括号的,表示输入流被当作内存数组并且可以直接对数据元素寻址。这就是所谓的“聚集流”。kernel代码和C代码之间的一个重要不同就是聚集流只能用向量类来寻址,而不是多个方括号(注:像数组那样)。

例如:A[x][y]是不允许的。

为了确定kernel该访问输出的哪一行/列,输出(注:指每次算得的输出矩阵中的一个值)的位置必须要确定。这是通过indexof()函数实现的,它返回一个整数表示输出域中的位置。

在while循环中,从矩阵A中的列和矩阵B中的值相乘(注:疑此处有误,AxB应该是A的行和B的列相乘),accumulator变量是乘积的结果。

和前面的sum例子一样,结果是不用方括号的。Brook+自动将结果写回正确的位置,也就是indexof()在输出流中的位置。

2.3.2Optimized Matrix Multiply Example

(注:更完善的矩阵乘法例子)

上面的kernel的一个缺点是:同样的数据在不同的地方被重用。例如:相邻的两个输出位置上,kernel使用了相同的行向量或是列向量。一般而言,从内存读取数据的开销大于从流处理器中读取。一个更完美的方法是在kernel中执行更多计算,这样读取操作就可以减少。下面是完善的矩阵乘法的代码:

kernel void
optimized_matmult(int loopVar0,
        float4 A1[][], float4 A2[][], float4 A3[][], float4 A4[][],
        float4 A5[][], float4 A6[][], float4 A7[][], float4 A8[][],
        float4 B1[][], float4 B2[][], float4 B3[][], float4 B4[][],
        out float4 C1<>, out float4 C2<>, out float4  C3<>, out float4 C4<>,
        out float4 C5<>, out float4 C6<>, out float4  C7<>, out float4 C8<>)
{
    // Setting zero
    float4 zero = float4(0.0f, 0.0f, 0.0f, 0.0f);

// Declaring and initializing accumulators
    float4 accumulator1 = zero;
    float4 accumulator2 = zero;
    float4 accumulator3 = zero;
    float4 accumulator4 = zero;
    float4 accumulator5 = zero;
    float4 accumulator6 = zero;
    float4 accumulator7 = zero;
    float4 accumulator8 = zero;

// Row number of output position
    int i = instance().y;

// Column number of output position
    int j = instance().x;

int k = 0;
    for(; k < loopVar0; ++k)
    {
        // Fetching values from A
        float4 A11 = A1[i][k];  float4 A22 = A2[i][k];
        float4 A33 = A3[i][k];  float4 A44 = A4[i][k];
        float4 A55 = A5[i][k];  float4 A66 = A6[i][k];
        float4 A77 = A7[i][k];  float4 A88 = A8[i][k];

// Fetching values from B
        float4 B11 = B1[k][j];  float4 B22 = B2[k][j];
        float4 B33 = B3[k][j];  float4 B44 = B4[k][j];

accumulator1 += A11.xxxx * B11.xyzw + A11.yyyy * B22.xyzw + A11.zzzz * B33.xyzw + A11.wwww * B44.xyzw;
        accumulator2 += A22.xxxx * B11.xyzw + A22.yyyy * B22.xyzw + A22.zzzz * B33.xyzw + A22.wwww * B44.xyzw;
        accumulator3 += A33.xxxx * B11.xyzw + A33.yyyy * B22.xyzw + A33.zzzz * B33.xyzw + A33.wwww * B44.xyzw;
        accumulator4 += A44.xxxx * B11.xyzw + A44.yyyy * B22.xyzw + A44.zzzz * B33.xyzw + A44.wwww * B44.xyzw;
        accumulator5 += A55.xxxx * B11.xyzw + A55.yyyy * B22.xyzw + A55.zzzz * B33.xyzw + A55.wwww * B44.xyzw;
        accumulator6 += A66.xxxx * B11.xyzw + A66.yyyy * B22.xyzw + A66.zzzz * B33.xyzw + A66.wwww * B44.xyzw;
        accumulator7 += A77.xxxx * B11.xyzw + A77.yyyy * B22.xyzw + A77.zzzz * B33.xyzw + A77.wwww * B44.xyzw;
        accumulator8 += A88.xxxx * B11.xyzw + A88.yyyy * B22.xyzw + A88.zzzz * B33.xyzw + A88.wwww * B44.xyzw;
    }

C1 = accumulator1;
    C2 = accumulator2;
    C3 = accumulator3;
    C4 = accumulator4;
    C5 = accumulator5;
    C6 = accumulator6;
    C7 = accumulator7;
    C8 = accumulator8;
}

Brook+ Programming (4)相关推荐

  1. Brook+ Programming

    翻译自AMD文档 2.1Runtime Options 在运行Brook+程序之前,需要注意一下环境变量: BRT_RUNTIME 这个环境变量允许你决定计算的后端是CPU(可以方便地调试)还是CAL ...

  2. Brook+ Programming (2)

    (接上一篇) 2.2.2 Building 使用如下步骤生成: 第一步: 用brcc编译 编译器可以在<BROOKROOT>/sdk/bin/下找到 brcc   [-hkrbfilxae ...

  3. Brook+ Programming (6)

    2.6 The Brook+ Runtiem API 现在版本的Brook+的特性都是完全改写了runtime引擎后的.为了提高性能和稳定性,新的C++ API提供给开发者以便能在低层用更有弹性的方式 ...

  4. Brook+ Programming (1)

    (接上一篇文章) Brook+的代码和C/C++的很像,但要注意以下几点: 第一,brcc像C编译器一样工作,也就是说编程要坚持标准C规范(例如:变量在代码段前声明). 对于更复杂的应用,要小心地区分 ...

  5. docker报错:driver failed programming external connectivity on endpoint, iptables:No chain by that name

    docker 报错: Error response from daemon: Cannot restart container hello: driver failed programming ext ...

  6. Java OOP(Object Oriented Programming)个人理解及总结

    面向对象编程(Object Oriented Programming,OOP,面向对象程序设计) 其三大特征:封装,继承,多态: 封装:解决数据的安全问题. 继承:解决代码的重用问题. 多态:解决程序 ...

  7. Structured Streaming编程 Programming Guide

    Structured Streaming编程 Programming Guide • Overview • Quick Example • Programming Model o Basic Conc ...

  8. 算法编程Algos Programming

    算法编程Algos Programming 不同算法的集合,用于编程比赛,如ACM ICPC. 算法按主题划分.大多数算法都可以从文件中按原样运行.每种算法都有一个参考问题,并对其时间和空间复杂度作了 ...

  9. CSE 3100 Systems Programming

    代做CSE 3100留学生作业.代写C/C++程序作业.代做Systems Programming作业.代写C/C++编程设计作业 CSE 3100 Systems Programming Homew ...

最新文章

  1. CQRS体系结构模式实践案例:Tiny Library:领域仓储与事件存储
  2. 搜索引擎Solr系列(二): Solr6.2.1 从MySql中导入数据
  3. Highly Available (Mirrored) Queues
  4. 个人信息安全影响评估指南_发布 | 网络安全标准实践指南—移动互联网应用程序(App)收集使用个人信息自评估指南...
  5. P1943-LocalMaxima_NOI导刊2009提高(1)【数论】
  6. Hibernate应用程序级可重复读取
  7. Linux:十条为系统管理员节省时间的命令
  8. python程序打包成安卓app教程_Python zipapp打包教程(超级详细)
  9. opencv视频播放
  10. 文件被后台程序占用无法删除_群晖NAS教程第十五节:查询群晖NAS硬盘空间占用情况,解决删除文件空间不增加问题...
  11. 再回首Java第二十二天
  12. 故障树最小割集程序化设计方案
  13. 工作效率低如何解决?
  14. Seaborn 绘图中设置字体及大小
  15. gloox1.0使用Emai格式的账号登录
  16. 弧度制和角度制的换算
  17. code review流程规范。
  18. 我在用的翻译软件 - 微软翻译+网易有道词典+谷歌翻译
  19. matlab-行相加、列相加
  20. 今天来聊一聊互联网35岁梗,这个行业真的不需要35岁以上从业人员?

热门文章

  1. 2021年黄岩中学高考成绩查询,2021台州中考分数线预测
  2. css marquee属性,css之marquee,让你的文字跳起来
  3. Big Endian 和 Little Endian 模式的区别
  4. win10系统提示 “你的账户已被停用,请向系统管理员咨询” 如何解决 ?
  5. Android安全输入设计与思考
  6. SQL Server 语句大全(3)-------常用函数
  7. 全景拍照返回键无保存
  8. Jetson Xavier、Jetson TX2、 1080(Ti)、2080显卡运行深度学习模型性能对比(英伟达开发平台VS常用显卡)
  9. Linux一句话精彩问答--2008/11/02更新--20071212pdf版本下载
  10. 前端裁切图片插件之cropper介绍