GPU编程和流式多处理器(五)

4. 条件代码

硬件实现了“条件代码”或CC寄存器,其中包含用于整数比较的常用4位状态向量(符号,进位,零,溢出)。可以使用比较指令(例如ISET来设置这些CC寄存器,并且它们可以通过谓词发散来指导执行流程。预测允许(或禁止)在warp内基于每个线程执行指令,而分歧则是较长指令序列的条件执行。因为SM内的处理器以warp粒度(一次32个线程)以SIMD方式执行指令,所以如果warp内的所有线程都采用相同的代码路径,则差异会导致执行的指令更少。

4.1. 谓词

由于管理发散和收敛的额外开销,编译器对短指令序列使用了谓词。多数指令的效果可以根据条件确定。如果条件不为TRUE,则禁止该指令。这种抑制发生得足够早,以至于预先确定的指令执行(例如加载/存储)和TEX抑制该指令原本会生成的内存流量。请注意,谓词对内存流量是否适合全局加载/存储合并没有影响。在warp中为所有加载/存储指令指定的地址,必须引用连续的存储位置,即使它们是有条件的。

当根据条件而变化的指令数量较少时,可以使用谓词。编译器使用的启发式方法,支持最多7条指令的谓词。除了避免如下所述的管理分支同步堆栈的开销外,谓词在发出微代码时还为编译器提供了更多的优化机会(例如指令调度)。C (? :)中的三元运算符,被视为有利于谓词的编译器提示。

清单2提供了一个很好的谓词示例,以微码表示。在共享内存位置执行原子操作时,编译器将发出在共享内存位置循环的代码,直到成功执行原子操作为止。所述LDSLK(负载共享和锁定)指令返回一个条件码,判断锁是否被获取。然后根据该条件代码确定执行操作的指令。

/ * 0058 * / LDSLK P0,R2,[R3];
/ * 0060 * / @ P0 IADD R2,R2,R0;
/ * 0068 * / @ P0 STSUL [R3],R2;
/ * 0070 * / @!P0 BRA 0x58;

该代码片段还强调了,谓词和分支如何协同工作。确定了最后一条指令,即在必要时尝试重新获取锁的条件分支。

4.2. 发散与收敛

谓词适用于条件代码的小片段,尤其是没有相应else语句中。对于大量的条件代码,由于每条指令都会执行,不管是否会影响计算,谓词的效率都会降低。当大量指令导致预测成本超过收益时,编译器将使用条件分支。当warp中的执行流程,根据条件采用不同的路径时,该代码称为divergent

NVIDIA对其硬件如何支持不同的代码路径的细节一无所知,并且保留在两代之间更改硬件实现的权利。硬件在每个warp中维护活动线程的位向量。对于标记为非活动的线程,以类似于谓词的方式抑制执行。在执行分支之前,编译器执行一条特殊指令,将该活动线程位向量压入堆栈。然后,该代码执行两次,一次是针对条件为TRUE的线程,另外是谓词为FALSE的线程。如Lindholm等人所述,此两阶段执行由分支同步堆栈管理。15

  • 如果warp的线程通过依赖于数据的条件分支发散,则warp会串行执行所采用的每个分支路径,从而禁用不在该路径上的线程,并且当所有路径完成时,这些线程将重新收敛到原始执行路径。SM使用分支同步堆栈,来管理发散和收敛的独立线程。分支发散仅在warp内发生;不管执行的是通用,还是不相交的代码路径,不同的warp都将独立执行。

PTX规范没有提及分支同步堆栈,公开存在的唯一证据是cuobjdump的反汇编输出。SSY指令推的状态下,如程序计数器和活动线程掩模压入堆栈; 该.S指令前缀突然发出这样的状态,如果任何活动线程没有采取分支,使这些线程执行的代码路径,其状态是由快照SSY

仅当执行线程可能分歧时,才需要SSY / .S。如果编译器可以保证线程在代码路径中保持一致,会出现SSY / .S不在括号内的分支。关于在CUDA中进行分支,在所有情况下,warp中的所有线程遵循相同的执行路径是最有效的。

清单2中的循环,包括一个很好的独立实例,说明了差异和收敛。所述SSY指令(偏移0x40的)和NOP.S指令(偏移0x78)分别括号发散和会聚的点。代码遍历LDSLK和随后的谓词指令,退出活动线程,直到编译器发现所有线程都将收敛,并且可以使用NOP.S指令,退出分支同步堆栈。

/ * 0040 * / SSY 0x80;
/ * 0048 * / BAR.RED.POPC RZ,RZ;
/ * 0050 * / LD R0,[R0];
/ * 0058 * / LDSLK P0,R2,[R3];
/ * 0060 * / @ P0 IADD R2,R2,R0;
/ * 0068 * / @ P0 STSUL [R3],R2;
/ * 0070 * / @!P0 BRA 0x58;
/ * 0078 * / NOP.S CC.T;

4.3. 特殊情况:最小值,最大值和绝对值

一些条件操作是如此普遍,以至于硬件会对其本身提供支持。整数和浮点算子均支持最小和最大运算,并将它们转换为单个指令。此外,浮点指令包括,否定或取源算子的绝对值的修饰符。

编译器可以很好地检测何时,表达了最小/最大运算,但是如果不希望碰碰运气,请为整数调用min()/ max()内部函数,或者为float调用fmin()/ fmax()价值观。

GPU编程和流式多处理器(五)的更多相关文章

  1. GPU编程和流式多处理器(六)

    GPU编程和流式多处理器(六) 5. 纹理和表面 读取和写入纹理和表面的指令,所引用的隐式状态,比其他指令要多得多.header中包含诸如基地址,尺寸,格式和纹理内容的解释之类的参数,该header是 ...

  2. GPU编程和流式多处理器(四)

    GPU编程和流式多处理器(四) 3.2. 单精度(32位) 单精度浮点支持是GPU计算的主力军.GPU已经过优化,可以在此数据类型上原生提供高性能,不仅适用于核心标准IEEE操作(例如加法和乘法),还 ...

  3. GPU编程和流式多处理器(三)

    GPU编程和流式多处理器(三) 3. Floating-Point Support 快速的本机浮点硬件是GPU的存在理由,并且在许多方面,它们在浮点实现方面都等于或优于CPU.全速支持异常可以根据每条 ...

  4. GPU编程和流式多处理器(二)

    GPU编程和流式多处理器(二) 2. 整数支持 SM具有32位整数运算的完整补充. 加法运算符的可选否定加法 乘法与乘法加法 整数除法 逻辑运算 条件码操作 to/from浮点转换 其它操作(例如,S ...

  5. GPU编程和流式多处理器

    GPU编程和流式多处理器 流式多处理器(SM)是运行CUDA内核的GPU的一部分.本章重点介绍SM的指令集功能. 流式多处理器(SM)是运行我们的CUDA内核的GPU的一部分.每个SM包含以下内容. ...

  6. GPU编程和流式多处理器(七)

    6. 杂项说明 6.1. warp级原语 warp作为执行的原始单元(自然位于线程和块之间),重要性对CUDA程序员显而易见.从SM 1.x开始,NVIDIA开始添加专门针对thread的指令. Vo ...

  7. GPU 编程入门到精通(五)之 GPU 程序优化进阶

    博主因为工作其中的须要,開始学习 GPU 上面的编程,主要涉及到的是基于 GPU 的深度学习方面的知识.鉴于之前没有接触过 GPU 编程.因此在这里特地学习一下 GPU 上面的编程. 有志同道合的小伙 ...

  8. GPU 编程入门到精通(四)之 GPU 程序优化

    博主因为工作其中的须要,開始学习 GPU 上面的编程,主要涉及到的是基于 GPU 的深度学习方面的知识,鉴于之前没有接触过 GPU 编程.因此在这里特地学习一下 GPU 上面的编程.有志同道合的小伙伴 ...

  9. GPU 编程入门到精通(三)之 第一个 GPU 程序

    博主因为工作其中的须要.開始学习 GPU 上面的编程,主要涉及到的是基于 GPU 的深度学习方面的知识,鉴于之前没有接触过 GPU 编程,因此在这里特地学习一下 GPU 上面的编程.有志同道合的小伙伴 ...

随机推荐

  1. hdu2870暴力或者dp优化

    题意:       给你一个矩阵,俩面的字母有一些转换规则,让你找到最大的相同字母字矩阵.. 思路:      一共有三种情况,就是a,b,c三种,我们可以分开来处理这三种情况,比如先处理a的,吧能转 ...

  2. 工具tip

    1 postman: chrome的插件,模拟http的get.post等各种请求 2 010: 二进制文件查看,支持很多文件格式和强大的脚本:010 Editor体验 3 BeyondCompare ...

  3. Conda基本使用方法

    anaconda/miniconda的安装 请点击查看我的博客 本教程全部命令操作均在CMD(win).terminal(win).终端(linux/Macos)中执行 使用前配置 因为anacond ...

  4. 【python】Leetcode每日一题-二叉搜索树节点最小距离

    [python]Leetcode每日一题-二叉搜索树节点最小距离 [题目描述] 给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 . 示例1: 输入:root = [4 ...

  5. ThreadLocal引起的一次线上事故

    > 线上用户存储数据后查看提示无权限 前言 不知道什么时候年轻的我曾一度认为Java没啥难度,没有我实现不了的需求,没有我解不了的bug 直到我遇到至今难忘的一个bug . 线上用户存储数据后查 ...

  6. Asp.NetCore Web开发之Nlog日志配置

    接着讲基于ASP .net Core 的web开发,这节主要讲一下如何使用和配置Nlog进行日志记录. 日志在开发中的作用是很重要的,使用日志,程序出了错误可以及时捕获并记录下来,开发人员可以通过日志 ...

  7. Base64文件上传(Use C#)

    Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,它是一种基于64个可打印字符来表示二进制数据的方法. 使用base64进行文件上传的具体流程是:前台使用js将文件转换为base64格 ...

  8. 没有发生GC也进入了安全点?这段关于安全点的JVM源码有点意思!

    文末 JVM 思维导图,有需要的可以自取 熟知并发编程的你认为下面这段代码的执行结果是怎么样的? 我如果说,执行流程是: t1 线程和 t2 线程一直执行 num 的累加操作 主线程睡眠 1 秒,1 ...

  9. win10 下安卓源码同步小技巧

    win10下,通过 清华镜像源 AOSP 可以快速拿到 100G 的 .repo  备份 然后 用 repo sync 就可以得到 安卓源码,爽不爽! 下载到win10 e盘下,用powershell ...

  10. [时间模块、random模块]

    [时间模块.random模块] time模块 在Python中,通常有这几种方式来表示时间: 时间戳(timestamp):通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏 ...