编写HSA内核
编写HSA内核
介绍
HSA提供类似于OpenCL的执行模型。指令由一组硬件线程并行执行。在某种程度上,这类似于 单指令多数据(SIMD)模型,但具有这样的便利:细粒度调度对于程序员而言是隐藏的,而不是使用SIMD向量作为数据结构进行编程。在HSA中,编写的代码将同时由多个线程(通常成百上千个)执行。解决方案将通过定义网格,工作组 和工作项的线程层次结构进行建模。
Numba的HSA支持提供了用于声明和管理此线程层次结构的工具。
CUDA程序简介
HSA执行模型类似于CUDA。HSA在ROC GPU上采用的内存模型也与CUDA相似。ROC的GPU具有专用于GPU存储器,因此,to_device()与copy_to_host()等需要按照CUDA。
这是CUDA术语到HSA的快速映射:
- Aworkitem等效于CUDA线程。
- Aworkgroup等效于CUDA线程块。
- Agrid等效于CUDA网格。
- Awavefront等效于CUDA warp。
内核声明
一个核心功能是指从CPU代码称为GPU功能。它具有两个基本特征:
- 内核无法显式返回值;所有结果数据都必须写入传递给函数的数组中(如果计算标量,则可能传递一个单元素数组);
- 内核在被调用时显式声明其线程层次结构:即工作组的数量和每个工作组的工作项的数量(注意,虽然内核仅编译一次,但可以使用不同的工作组大小或网格大小多次调用)。
用Numba编写HSA内核非常类似于为CPU编写JIT函数:
@roc.jit
def increment_by_one(an_array):
"""
Increment all array elements by one.
"""
# code elided here; read further for different implementations
内核调用
通常以以下方式启动内核:
itempergroup = 32
groupperrange = (an_array.size + (itempergroup - 1)) // itempergroup
increment_by_one[groupperrange, itempergroup](an_array)
注意到两个步骤:
- 通过指定多个工作组(或“每个网格的工作组”)和每个工作组的多个工作项来实例化内核。两者的乘积将给出启动的工作项总数。内核实例化是通过采用已编译的内核函数(在此处increment_by_one)并用整数元组对其进行索引来完成的。
- 通过将输入数组(如果需要,以及任何单独的输出数组)传递给内核来运行内核。默认情况下,运行内核是同步的:当内核完成执行并且数据被同步时,该函数返回。
选择工作组大小
在声明内核所需的工作项数量时,具有两级层次结构似乎很奇怪。工作组的大小(即每个工作组的工作项数)通常很关键:
- 在软件方面,工作组的大小确定了多少线程共享内存的给定区域。
- 在硬件方面,工作组的大小必须足够大
独占执行单位。
多维工作组和网格
为了帮助处理多维数组,HSA指定多维工作组和网格。在上面的示例中,可以使itempergroupandgroupperrange元组为一个,两个或三个整数。与等效大小的一维声明相比,这不会改变所生成代码的效率或行为,但可以帮助以更自然的方式编写算法。
工作项定位
运行内核时,内核函数的代码由每个线程执行一次。因此,它必须知道它在哪个线程中,以便知道它负责哪个数组元素(复杂算法可以定义更复杂的任务,但是基本原理是相同的)。
一种方法是让线程确定其在网格和工作组中的位置,然后手动计算相应的数组位置:
@roc.jit
def increment_by_one(an_array):
# workitem id in a 1D workgroup
tx = roc.get_local_id(0)
# workgroup id in a 1D grid
ty = roc.get_group_id(0)
# workgroup size, i.e. number of workitem per workgroup
bw = roc.get_local_size(0)
# Compute flattened index inside the array
pos = tx + ty * bw
# The above is equivalent to pos = roc.get_global_id(0)
if pos < an_array.size: # Check array boundaries
an_array[pos] += 1
注意
除非确定工作组大小和网格大小是阵列大小的除数,否则必须如上所述检查边界。
get_local_id(),get_local_size(),get_group_id()和 get_global_id()是由HSA后端为知道thread层次结构的几何形状和该几何形状内的当前工作项的位置的唯一目的提供特殊功能。
numba.roc.get_local_id(dim)
取得要查询的维度的索引
返回给定维度的当前工作组中的本地工作项ID。对于一维工作组,索引是一个整数,范围从0(含)到numba.roc.get_local_size()异(exclusive)。
numba.roc.get_local_size(dim)
取得要查询的维度的索引
返回给定维度上工作组的大小。实例化内核时声明该值。对于给定内核中的所有工作项,该值相同,即使属于不同的工作组(即,每个工作组“已满”)也是如此。
numba.roc.get_group_id(dim)
取得要查询的维度的索引
在启动了内核的工作组网格中返回工作组ID。
numba.roc.get_global_id(dim)
取得要查询的维度的索引
返回给定维度的全局工作项ID。与numba.roc .get_local_id()不同,此数字对于网格中的所有工作项都是唯一的。
编写HSA内核的更多相关文章
- 编写CUDA内核
编写CUDA内核 介绍 与用于CPU编程的传统顺序模型不同,CUDA具有执行模型.在CUDA中,编写的代码将同时由多个线程(通常成百上千个)执行.解决方案将通过定义网格,块和线程层次结构进行建模. N ...
- 在Ubuntu上为Android系统编写Linux内核驱动程序(老罗学习笔记1)
这里,我们不会为真实的硬件设备编写内核驱动程序.为了方便描述为Android系统编写内核驱动程序的过程,我们使用一个虚拟的硬件设备,这个设备只有一个4字节的寄存器,它可读可写.想起我们第一次学习程序语 ...
- 在Ubuntu上为Android系统编写Linux内核驱动程序
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6568411 在智能手机时代,每个品牌的手机都有 ...
- 使用FormatMessage函数编写一个内核错误码查看器
在编写驱动程序的时候,常用的一个结构是NTSTATUS,它来表示操作是否成功,但是对于失败的情况它的返回码过多,不可能记住所有的情况,应用层有一个GetLastError函数,根据这个函数的返回值可以 ...
- c++编写webui内核 .
http://blog.csdn.net/sx1989827/article/details/8068779 #pragma once #include <mshtmhst.h> #inc ...
- 用JAVA编写浏览器内核之实现javascript的document对象与内置方法
原创文章.转载请注明. 阅读本文之前,您须要对浏览器怎样载入javascript有一定了解. 当然,对java与javascript本身也须要了解. 本文首先介绍浏览器载入并执行javascript的 ...
- 布客·ApacheCN 翻译/校对/笔记整理活动进度公告 2020.1
注意 请贡献者查看参与方式,然后直接在 ISSUE 中认领. 翻译/校对三个文档就可以申请当负责人,我们会把你拉进合伙人群.翻译/校对五个文档的贡献者,可以申请实习证明. 请私聊片刻(52981514 ...
- 内核第三讲,进入ring0,以及编写第一个内核驱动程序.
内核第三讲,进入ring0,以及编写第一个内核驱动程序. PS: 请下配置双机调试,下方有可能用到.如果不配置,则你可以不用调试, 博客连接: http://www.cnblogs.com/iBina ...
- linux 内核邮件列表
第一节 - 一般性问题 1. 为什么有些时候使用“GNU/Linux"而另一些时候使用“Linux”? 答:在这个FAQ中,我们尝试使用“linux”或者“linux kernel”来表示内 ...
随机推荐
- 解决小程序中Data.parse()获取时间戳IOS不兼容
由于与后台接口必须对比时间戳所以首先得前台获取时间戳.刚开始是获取手机本地时间,但用户改了时间就废了..... 后来就从服务器上获取个时间再转换为时间戳(是不是很操蛋,先从服务器上获取在TM的自己比较 ...
- 在Android的App中动态的加载Java类
原文的地址:http://yenliangl.blogspot.com/2009/11/dynamic-loading-of-classes-in-your.html 我正在编写一个应用程序能够加载别 ...
- hdu3018 一笔画问题
题意: 给你一幅画,这幅画由点和边构成,问你最少几笔能把这幅画画完. 思路: 这个题目的结论比较巧妙,首先我们考虑下,如果给的图是欧拉图,或者是条欧拉回路,那么我们一笔就搞定了, ...
- Iptables防火墙实验
先说明一下环境,这里有四台主机,中间的Centos充当防火墙.右上角的win XP和右下角的Rhel7充当服务器,最左边的win7充当主机.四者之间的网卡都已经配置好.而且我们已经在Centos6.5 ...
- 【转】Python调用C语言动态链接库
转自:https://www.cnblogs.com/fariver/p/6573112.html 动态链接库在Windows中为.dll文件,在linux中为.so文件.以linux平台为例说明py ...
- 15 个让新手爱不释手的 Python 高级库
为什么我喜欢 Python ? 对于初学者来说,这是一种简单易学的编程语言:另一个原因:大量开箱即用的第三方库,正是 23 万个由用户提供的软件包使得 Python 真正强大和流行 在本文中,我挑选了 ...
- python爬虫——拉钩网python岗位信息
之前爬取的网页都是采用"GET"方法,这次爬取"拉勾网"是采取了"POST"的方法.其中,"GET"和"POS ...
- 如何实现一个简易版的 Spring - 如何实现 AOP(上)
前言 本文是「如何实现一个简易版的 Spring 系列」的第五篇,在之前介绍了 Spring 中的核心技术之一 IoC,从这篇开始我们再来看看 Spring 的另一个重要的技术--AOP.用过 Spr ...
- kubernetes dashboard延长自动超时注销
方法1:部署清单时,修改yaml文件,添加 container.Args 增加 --token-ttl=43200 其中43200是设置自动超时的秒数.也可以设置 token-ttl=0 以完全禁用超 ...
- CentOS7 / CentOS8 设置终端屏幕分辨率
Centos7 修改文件 /boot/grub2/grub.cfg 搜索 linux16 / /vmlinuz-3.10.0-123.el7.x86_64 root=UUID=881ac4e6-4a5 ...