编写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_sizedim

取得要查询的维度的索引

返回给定维度上工作组的大小。实例化内核时声明该值。对于给定内核中的所有工作项,该值相同,即使属于不同的工作组(即,每个工作组“已满”)也是如此。

numba.roc.get_group_iddim

取得要查询的维度的索引

在启动了内核的工作组网格中返回工作组ID。

numba.roc.get_global_iddim

取得要查询的维度的索引

返回给定维度的全局工作项ID。与numba.roc .get_local_id()不同,此数字对于网格中的所有工作项都是唯一的。

编写HSA内核的更多相关文章

  1. 编写CUDA内核

    编写CUDA内核 介绍 与用于CPU编程的传统顺序模型不同,CUDA具有执行模型.在CUDA中,编写的代码将同时由多个线程(通常成百上千个)执行.解决方案将通过定义网格,块和线程层次结构进行建模. N ...

  2. 在Ubuntu上为Android系统编写Linux内核驱动程序(老罗学习笔记1)

    这里,我们不会为真实的硬件设备编写内核驱动程序.为了方便描述为Android系统编写内核驱动程序的过程,我们使用一个虚拟的硬件设备,这个设备只有一个4字节的寄存器,它可读可写.想起我们第一次学习程序语 ...

  3. 在Ubuntu上为Android系统编写Linux内核驱动程序

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6568411 在智能手机时代,每个品牌的手机都有 ...

  4. 使用FormatMessage函数编写一个内核错误码查看器

    在编写驱动程序的时候,常用的一个结构是NTSTATUS,它来表示操作是否成功,但是对于失败的情况它的返回码过多,不可能记住所有的情况,应用层有一个GetLastError函数,根据这个函数的返回值可以 ...

  5. c++编写webui内核 .

    http://blog.csdn.net/sx1989827/article/details/8068779 #pragma once #include <mshtmhst.h> #inc ...

  6. 用JAVA编写浏览器内核之实现javascript的document对象与内置方法

    原创文章.转载请注明. 阅读本文之前,您须要对浏览器怎样载入javascript有一定了解. 当然,对java与javascript本身也须要了解. 本文首先介绍浏览器载入并执行javascript的 ...

  7. 布客&#183;ApacheCN 翻译/校对/笔记整理活动进度公告 2020.1

    注意 请贡献者查看参与方式,然后直接在 ISSUE 中认领. 翻译/校对三个文档就可以申请当负责人,我们会把你拉进合伙人群.翻译/校对五个文档的贡献者,可以申请实习证明. 请私聊片刻(52981514 ...

  8. 内核第三讲,进入ring0,以及编写第一个内核驱动程序.

    内核第三讲,进入ring0,以及编写第一个内核驱动程序. PS: 请下配置双机调试,下方有可能用到.如果不配置,则你可以不用调试, 博客连接: http://www.cnblogs.com/iBina ...

  9. linux 内核邮件列表

    第一节 - 一般性问题 1. 为什么有些时候使用“GNU/Linux"而另一些时候使用“Linux”? 答:在这个FAQ中,我们尝试使用“linux”或者“linux kernel”来表示内 ...

随机推荐

  1. Windows新建选项排序

    运行输入:regedit 然后找到:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Discardable\P ...

  2. Python第一章-基础知识

    第一章:基础知识 1.1 安装python.     直接官网下载最新的python然后默认安装就可以了,然后开始菜单里找到pyhton *.*.* Shell.exe运行python的交互shell ...

  3. 【python】Leetcode每日一题-寻找旋转排序数组中的最小元素2

    [python]Leetcode每日一题-寻找旋转排序数组中的最小元素2 [题目描述] 已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组.例如,原数组nums ...

  4. 第四部分 数据搜索之使用HBASE的API实现条件查询

    因为数据清洗部分需要用到Mapreduce,所以先解决hbase的问题,可以用命令先在hbase存一下简单的数据进行查询,之后只要替换数据就可以实现了原本功能 在看该部分前,确保Hase API看了, ...

  5. SparkSQL电商用户画像(二)之如何构建画像

    四. 如何构建电商用户画像 4.1 构建电商用户画像技术和流程 构建一个用户画像,包括数据源端数据收集.数据预处理.行为建模.构建用户画像 有些标签是可以直接获取到的,有些标签需要通过数据挖掘分析到! ...

  6. JMeter关联陌生又熟悉

    JMeter关联是什么 JMeter关联,这几个字看着可能会有点陌生,实际上却是工作中经常会做的一件事情,尤其是接口自动化,它指的是把一个接口的响应作为另一个接口的参数,从而把接口关联起来. JMet ...

  7. 依赖倒置原则(Dependence Inversion Principle)

    目录 背景 说明 例子 "倒置"的解释 总结 参考资料 背景 这几天组内的人一起学习DDD,里面再次提到了依赖倒置原则,在这学习过程中,大家又讨论了一下依赖倒置原则. 说明 采用依 ...

  8. Solon Aop 特色开发(1)注入或手动获取配置

    常规操作,先启动 Solon public class App{ public void main(String[] args){ Solon.start(App.class, args); } } ...

  9. ES6学习-1 啥是ES6啊

    我不准备刨根问底,找寻他的十八辈祖先,希望用最简单的方式能够说明白ES6是个啥,come on baby ES6的全称是ECMAScript 6.0,他于2015 年 6 月正式发布,它的目标是使得 ...

  10. mysql 索引十连问| 剑指 offer - mysql

    以下是结合网上及此前面试时遇到的一些关于mysql索引的面试题. 若对mysql索引不太了解可先翻阅相关文章 大白话 mysql 之深入浅出索引原理 - 上 大白话 mysql 之深入浅出索引原理 - ...