编写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. Python的套接字、IPv4和简单的客户端/服务器编程

    #!/usr/bin/env python # -*- coding: utf-8 -*- import socket from binascii import hexlify import sys ...

  2. hdu4717 三分(散点的移动)

    题意:      给你一些点,这些点有各自的初始位置,移动速度和方向,问你什么时候任意两点中最长的距离最小,求时刻和此时的距离.. 思路:      感觉题目很赞,一开始想不到三分,因为么有办法证明他 ...

  3. UVA10340子序列

    题意:       给你两个串,问你第二个第一个串是否是第一个串删除0个或多个字母得到的? 思路:       直接模拟就行了,在第二个串中去按顺序更新第一个串的下标,好像没说明白啊,不管了,水题,不 ...

  4. UVA10020(最小区间覆盖)

    题意:       给你一个区间[0,m]和一些小的区间[l,r]让你选择最少的小区间个数去把整个区间覆盖起来. 思路:       算是比较经典的贪心题目吧(经典于难度没什么对应关系),大体思路可以 ...

  5. PAT 乙级 -- 1012 -- 数字分类

    题目简介 给定一系列正整数,请按要求对数字进行分类,并输出以下5个数字: A1 = 能被5整除的数字中所有偶数的和: A2 = 将被5除后余1的数字按给出顺序进行交错求和,即计算n1-n2+n3-n4 ...

  6. linux ptrace学习

    ptrace提供了一种使父进程得以监视和控制其它进程的方式,它还能够改变子进程中的寄存器和内核映像,因而可以实现断点调试和系统调用的跟踪.学习linux的ptrace是为学习android adbi框 ...

  7. 如何以最简单的方式安装 KALI 渗透测试框架系统

    0x01 第一步下载 KALI 百度搜索 KALI 官网,找到下载区,我选的是 64 位标准版,但是推荐下载 32 位(功能貌似更全) 这个为下载后的 iso 镜像文件 0x02 第二步打开虚拟机,配 ...

  8. Shiro反序列化漏洞复现

    Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码和会话管理.使用Shiro的易于理解的API,可以快速.轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企 ...

  9. java.lang.NoSuchMethodError: org.springframework.util.Assert.state(ZLjava/util/function/Supplier;)V

    更多精彩见微信公众号 at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildMergedCo ...

  10. 在Visual Studio 中使用git——文件管理-中(五)

    在Visual Studio 中使用git--什么是Git(一) 在Visual Studio 中使用git--给Visual Studio安装 git插件(二) 在Visual Studio 中使用 ...