编写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. featureCarousel.js 3d轮播图插件

    jQuery Feature Carousel 插件是国外的一比较优秀的旋转木马图片插件. 点击这里进入原文. 插件特点: 1.处理div的3d旋转木马效果. 2.支持一个中心,2个侧面的功能 3.中 ...

  2. LA3213加密

    题意:       白书上有些题的题意说的太蛋疼了,这个题的意思是说有两种加密方式,一种是交换位置,另一种是一一映射,交换位置是指如ABCD 可以加密成DCBA 也可以加密成ACBD就是把某些字母的位 ...

  3. POJ1258最小生成树简单题

    题意:       给你个图,让你求一颗最小生成树. 思路:      裸题,克鲁斯卡尔或者普利姆都行. #include<stdio.h> #include<algorithm&g ...

  4. 【Mybtais】Mybatis 插件 Plugin开发(一)动态代理步步解析

    需求: 对原有系统中的方法进行'拦截',在方法执行的前后添加新的处理逻辑. 分析: 不是办法的办法就是,对原有的每个方法进行修改,添加上新的逻辑:如果需要拦截的方法比较少,选择此方法到是会节省成本.但 ...

  5. 你管这破玩意叫CPU?

    每次回家开灯时你有没有想过,用你按的开关实际上能打造出 复杂的 CPU来,只不过需要的数量可能比较多,也就几十亿个吧. 伟大的发明 过去200年人类最重要的发明是什么?蒸汽机?电灯?火箭?这些可能都不 ...

  6. Django(1)初识Django

    前言 Django是一个开放源代码的Web应用框架,由Python写成,最初用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站,即CMS(内容管理系统)软件,于2005年7月在BSD许可证下发布,这 ...

  7. Jenkins+Git的搭建和自动部署

    前言 Jenkins在工作中都使用过,之前都是运维去搭建部署,弄好了之后给我一个网址去构建项目就可以了,所以也都是一直没了解过安装过程. 今天在自己的服务器上搭建了一遍,中间有遇到很多坑,特在此归纳总 ...

  8. 微信小程序中的常见弹框

    显示加载中的提示框 wx.showLoading() 当我们正在在进行网络请求时,常常就需要这个提示框 手动调用wx.hideLoading()方法才能够关闭这个提示框,通常在数据请求完毕时就应该关闭 ...

  9. 国家密码标准-商密SM2官方文档整理

    SM2官方文档整理 算法原理 SM2算法介绍 我国自主知识产权的商业密码算法,是ECC(椭圆加密算法)的一种,基于椭圆曲线离散对数问题(公钥密码体制所依据的难题主要为大素数分解问题.离散对数问题.椭圆 ...

  10. Git 系列教程(12)- 分支的新建与合并

    实际工作场景 可能会遇到的工作流 开发某个网站 为实现某个新的用户需求,创建一个分支 在这个分支上开展新工作 正在此时,你突然接到一个电话说有个很严重的问题需要紧急修补,你将按照如下方式来处理: 切换 ...