CUDA 8混合精度编程

Mixed-Precision Programming with CUDA 8

论文地址:https://devblogs.nvidia.com/mixed-precision-programming-cuda-8/

更新,2019年3月25日:最新的Volta和Turing GPU现在加入了张量核,加速了某些类型的FP16矩阵数学。这使得在流行的人工智能框架中进行更快、更容易的混合精度计算成为可能。使用张量磁芯需要使用CUDA9或更高版本。NVIDIA还为TensorFlow、PyTorch和MXNet添加了自动混合精度功能。想多学点还是自己试试?在这里获取流行的人工智能框架的tensor核心优化示例。

在软件开发的实践中,程序员很早就学会了使用正确的工具来完成工作的重要性。当涉及到数值计算时,这一点尤其重要,因为在精度、精度和性能之间的权衡使得选择数据的最佳表示非常重要。随着Pascal GPU体系结构和CUDA 8的引入,NVIDIA正在扩展可用于混合精度计算的工具集,包括新的16位浮点和8/16位整数计算功能。

“随着在不同精度下计算的相对成本和易用性的发展,由于体系结构和软件的变化,以及GPU等加速器的破坏性影响,将看到混合精度算法的开发和使用越来越多。”—Nick Higham,Richardson应用数学教授,曼彻斯特大学。

许多技术和高性能计算机应用需要32位(单浮点数,或FP32)或64位(双浮点数,或FP64)浮点的高精度计算,甚至还有依赖更高精度(128位或256位浮点)的GPU加速应用。但是有许多应用需要低精度的算法。例如,在快速增长的深度学习领域的研究人员发现,由于训练深层神经网络时使用的反向传播算法,深层神经网络结构对错误具有自然的弹性,一些人认为16位浮点(半精度,或FP16)足以训练神经网络。

与精度更高的FP32或FP64相比,存储FP16(半精度)数据减少了神经网络的内存使用,允许训练和部署更大的网络,并且FP16数据传输比FP32或FP64传输花费的时间更少。此外,对于许多网络,可以使用8位整数计算来执行深度学习推断,而不会对精度产生显著影响。

除了深度学习之外,使用摄像机或其真实传感器数据的应用程序通常不需要高精度浮点计算,因为传感器生成低精度或低动态范围数据。射电望远镜处理的数据就是一个很好的例子。正如将在本文后面看到的,使用8位整数计算可以大大加快用于处理射电望远镜数据的互相关算法。

在计算方法中结合使用不同的数值精度称为混合精度。NVIDIA Pascal体系结构通过在32位数据路径中添加向量指令(将多个操作打包到一个数据路径中),为能够利用较低精度计算的应用程序提供了旨在提供更高性能的功能。具体地说,这些指令操作16位浮点数据(“半”或FP16)和8位和16位整数数据(INT8和INT16)。

新的NVIDIA Tesla P100由GP100 GPU供电,可以以FP32的两倍吞吐量执行FP16算法。GP102(Tesla P40和NVIDIA Titan X)、GP104(Tesla P4)和GP106 gpu都支持指令,这些指令可以对2和4元素8位向量执行整数点积,并累加为32位整数。这些指令对于实现高效的深度学习推理以及射电天文学等其应用具有重要价值。

在这篇文章中,将提供一些有关半精度浮点的详细信息,并提供使用FP16和INT8矢量计算在Pascal gpu上可实现的性能的详细信息。还将讨论各种CUDA平台库和api提供的混合精度计算能力。

A Bit (or 16) about Floating Point Precision

每一位计算机科学家都应该知道,浮点数提供了一种表示法,允许在计算机上对实数进行近似,同时在范围和精度之间进行权衡。浮点数将实值近似为一组有效数字(称为尾数或有效位),然后按固定基数的指数缩放(当前大多数计算机上使用的IEEE标准浮点数的基数为2)。

常见的浮点格式包括32位,称为“单精度”(“float”在C派生的编程语言中)和64位,称为“双精度”(“double”)。根据IEEE 754标准的定义,32位浮点值包括符号位、8个指数位和23个尾数位。64位双精度包含一个符号位、11个指数位和52个尾数位。在本文中,对(较新的)IEEE754标准16位浮点半类型感兴趣,包含一个符号位、5个指数位和10个尾数位,如图1所示。

Figure 1: 16-bit half-precision floating point (FP16) representation: 1 sign bit, 5 exponent bits, and 10 mantissa bits.

为了了解精度16位之间的差异,FP16可以表示2-14和215(其指数范围)之间2的每个幂的1024个值。这是30720个值。与之形成对比的是FP32,在2-126和2127之间,每2次幂的值约为800万。这大约是20亿的价值,差别很大。那么为什么要使用像FP16这样的小浮点格式呢?一句话,表演。

NVIDIA Tesla P100(基于GP100 GPU)支持双向矢量半精度融合乘法加法(FMA)指令(操作码HFMA2),可以以与32位FMA指令相同的速率发出该指令。这意味着半精度算法在P100上的吞吐量是单精度算法的两倍,是双精度算法的四倍。具体来说,启用NVLink的P100(SXM2模块)能够达到21.2teraflop/s的半精度。有了这么大的性能优势,应该看看如何使用。

在使用降低精度时要记住的一点是,由于FP16的标准化范围较小,生成次标准化数(也称为非标准化数)的概率增加。因此,NVIDIA的gpu必须在低标准数上实现FMA操作,并具有完整的性能。有些处理器没有,性能会受到影响。(注意:启用“flush to zero”仍有好处)。请参阅文章“CUDA Pro Tip:Flush Denormals with Confidence”。)

High Performance with Low-Precision Integers

浮点数结合了高动态范围和高精度,但也有不需要动态范围的情况,因此整数可以完成这项工作。甚至有些应用程序处理的数据精度很低,因此可以使用非常低的精度存储(如C short或char/byte类型)。

Figure 2: New DP4A and DP2A instructions in Tesla P4 and P40 GPUs provide fast 2- and 4-way 8-bit/16-bit integer vector dot products with 32-bit integer accumulation.

对于此类应用,最新的Pascal gpu(GP102、GP104和GP106)引入了新的8位整数4元向量点积(DP4A)和16位2元向量点积(DP2A)指令。DP4A执行两个4元素向量A和B(每个向量包含存储在32位字中的4个单字节值)之间的向量点积,将结果存储为32位整数,并将其添加到第三个参数C(也是32位整数)中。见图2。DP2A是类似的指令,其中a是16位值的2元向量,B是8位值的4元向量,不同类型的DP2A为2路点积选择高字节对或低字节对。这些灵活的指令对于线性代数计算(如矩阵乘法和卷积)非常有用。对于实现用于深度学习推理的8位整数卷积特别强大,通常用于部署用于图像分类和对象检测的深度神经网络。图3显示了在AlexNet上使用INT8卷积在Tesla P4 GPU上实现的改进的功率效率。

Figure 3: Using INT8 computation on the Tesla P4 for deep learning inference provides a very large improvement in power efficiency for image recognition using AlexNet and other deep neural networks, when compared to FP32 on previous generation Tesla M4 GPUs. Efficiency of this computation on Tesla P4 is up to 8x more efficient than an Arria10 FPGA, and up to 40x more efficient than an Intel Xeon CPU. (AlexNet, batch size = 128, CPU: Intel E5-2690v4 using Intel MKL 2017, FPGA is Arria10-115. 1x M4/P4 in node, P4 board power at 56W, P4 GPU power at 36W, M4 board power at 57W, M4 GPU power at 39W, Perf/W chart using GPU power.)

DP4A计算总共8个整数操作的等效值,DP2A计算4个。这使Tesla P40(基于GP102)的峰值整数吞吐量达到47 TOP/s(Tera操作/秒)。

DP4A的一个应用实例是在射电望远镜数据处理管道中常用的互相关算法。与光学望远镜一样,较大的射电望远镜可以分辨宇宙中较暗和较远的物体;但是,建造越来越大的单片单天线射电望远镜是不实际的。取而代之的是,射电天文学家在大面积上建造了许多天线阵列。要使用这些望远镜,来自所有天线的信号必须是互相关的,这是一种高度并行的计算,其成本与天线数量成正比。由于射电望远镜元件通常捕获非常低精度的数据,所以信号的互相关不需要浮点运算。gpu已经被用于射电天文学互相关的制作,但通常使用FP32计算。DP4A的引入为这种计算提供了更高的功率效率。

图4显示了修改互相关代码以使用DP4A的结果,从而在具有默认时钟的Tesla P40 GPU上提高了4.5倍的效率(与P40上的FP32计算相比),并在设置GPU时钟以降低温度(从而降低泄漏电流)的情况下提高了6.4倍。总的来说,新代码比上一代Tesla M40 GPU上的FP32交叉相关效率高出近12倍(图片来源:Kate Clark)。

Figure 4: INT8 vector dot products (DP4A) improve the efficiency of radio astronomy cross-correlation by a large factor compared to FP32 computation.

Mixed Precision Performance on Pascal GPUs

半精度(FP16)格式对gpu来说并不新鲜。事实上,FP16作为一种存储格式在NVIDIA GPUs上已经支持了很多年,主要用于降低精度的浮点纹理存储和过滤等特殊用途的操作。Pascal GPU架构实现了通用的IEEE 754 FP16算法。高性能FP16在Tesla P100(GP100)上以全速支持,在其Pascal gpu(GP102、GP104和GP106)上以较低的吞吐量(类似于双精度)支持,如下表所示。

GP102-GP106支持8位和16位DP4A和DP2A点产品指令,但GP100不支持。表1显示了基于Pascal的Tesla gpu上不同数值指令的算术吞吐量。

Table 1: Pascal-based Tesla GPU peak arithmetic throughput for half-, single-, and double-precision fused multiply-add instructions, and for 8- and 16-bit vector dot product instructions. (Boost clock rates are used in calculating peak throughputs. TFLOP/s: Tera Floating-point Operations per Second. TIOP/s: Tera Integer Operations per Second.

Mixed-Precision Programming with NVIDIA Libraries

从应用程序的混合精度中获益的最简单方法是利用NVIDIA GPU库中对FP16和INT8计算的支持。NVIDIA SDK的密钥库现在支持计算和存储的各种精度。

表2显示了当前对FC16和It8在关键CUDA库以及PTX组件和CUDA C/C++内部的支持。

Table 2: CUDA 8 FP16 and INT8 API and library support.

cuDNN

cuDNN是一个原始程序库,用于训练和部署深层神经网络。cuDNN 5.0包括对前向卷积的FP16支持,以及对FP16后向卷积的5.1附加支持。库中的所有其例程都是内存绑定的,因此FP16计算不利于性能。因此,这些例程使用FP32计算,但支持FP16数据输入和输出。cuDNN 6将增加对INT8推理卷积的支持。

TensorRT

TensorRT是一个高性能的深度学习推理机,用于深度学习应用程序的生产部署,自动优化训练神经网络的运行时性能。TensorRT v1支持FP16进行推理卷积,v2支持INT8进行推理卷积。

cuBLAS

cuBLAS是一个用于密集线性代数的GPU库,是基本线性代数子程序BLAS的一个实现。cuBLAS在几个矩阵乘法例程中支持混合精度。cubrashgemm是一个FP16密集矩阵乘法例程,使用FP16进行计算以及输入和输出。cubassgemex()在FP32中计算,但输入数据可以是FP32、FP16或INT8,输出可以是FP32或FP16。cublasgem()是CUDA 8中的一个新例程,允许指定计算精度,包括INT8计算(使用DP4A)。

将根据需要添加对具有FP16计算和/或存储的更多BLAS级别3例程的支持,因此如果需要,请与联系。级别1和级别2的BLAS例程是内存限制的,因此减少精度计算是不利的。

cuFFT

cuft是CUDA中一种流行的快速傅立叶变换库。从CUDA 7.5开始,cuft支持单GPU fft的FP16计算和存储。FP16 FFT比FP32快2倍。FP16计算需要一个计算能力为5.3或更高的GPU(Maxwell架构)。当前大小限制为2的幂,并且不支持R2C或C2R转换的实际部分上的跨步。

cuSPARSE

cuSPARSE是一个用于稀疏矩阵的GPU加速线性代数例程库。cuSPARSE支持几个例程的FP16存储(`cusparseXtcsrmv()`、`cusparseCsrsv_analysisEx()`、`cusparseCsrsv_solvex()`、`cusparseScsr2cscEx()`和`cusparseCsrilu0Ex()`)。正在研究cuSPARSE的FP16计算。

Using Mixed Precision in your own CUDA Code

对于定制的CUDA C++内核和推力并行算法库的用户,CUDA提供了需要从FP16和It8计算、存储和I/O.中充分利用的类型定义和API。

FP16 types and intrinsics

对于FP16,CUDA定义了CUDA include路径中包含的头文件“CUDA_FP16.h”中的“half”和“half 2”类型。此头还定义了一组完整的内部函数,用于对“半”数据进行操作。例如,下面显示标量FP16加法函数“hadd()”和双向向量FP16加法函数“hadd2()”的声明。

__device__ __half __hadd ( const __half a, const __half b );

__device__ __half2 __hadd2 ( const __half2 a, const __half2 b );

`cuda_fp16.h`为算术、比较、转换和数据移动以及其数学函数定义了一整套半精度的内部函数。所有这些都在CUDA Math API文档中描述。

尽可能使用“half2”向量类型和内部函数以获得最高的吞吐量。GPU硬件算术指令一次对2个FP16值进行操作,并打包在32位寄存器中。表1中的峰值吞吐量数字采用“半2”矢量计算。如果使用标量“half”指令,则可以达到峰值吞吐量的50%。同样,要在从FP16阵列加载和存储到FP16阵列时获得最大带宽,需要对“半2”数据进行矢量访问。理想情况下,可以通过加载和存储“float2”或“float4”类型并强制转换到“half2”或从“half2”转换到“half2”,进一步将加载矢量化以获得更高的带宽。有关相关示例,请参阅所有Pro-Tip博客文章的上一篇平行文章。

下面的示例代码演示如何使用CUDA的uu hfma()(半精度融合乘法加法)和其内部函数计算半精度AXPY(a*X+Y)。该示例的完整代码在Github上提供,展示了如何在主机上初始化半精度数组。重要的是,当开始使用半类型时,可能需要在主机端代码中的半值和浮点值之间进行转换。这篇来自FabianGiesen的博客文章包含了一些快速CPU类型转换例程(请参阅相关的要点以获得完整的源代码)。在这个例子中使用了一些Giesen的代码。

__global__

void haxpy(int n, half a, const half *x, half *y)

{

int start = threadIdx.x + blockDim.x * blockIdx.x;

int stride = blockDim.x * gridDim.x;

#if __CUDA_ARCH__ >= 530

int n2 = n/2;

half2 *x2 = (half2*)x, *y2 = (half2*)y;

for (int i = start; i < n2; i+= stride)

y2[i] = __hfma2(__halves2half2(a, a), x2[i], y2[i]);

// first thread handles singleton for odd arrays

if (start == 0 && (n%2))

y[n-1] = __hfma(a, x[n-1], y[n-1]);

#else

for (int i = start; i < n; i+= stride) {

y[i] = __float2half(__half2float(a) * __half2float(x[i])

+ __half2float(y[i]));

}

#endif

}

Integer Dot Product Intrinsics

CUDA在头文件“smɤu intrinsics.h”(smɤ61是对应于GP102、GP104和GP106的sm体系结构)中定义8位和16位点产品(前面描述的DP4A和DP2A指令)的内部函数。也称为计算能力6.1。为了方便起见,DP4A内部函数有“int”和“char4”两种版本,有符号和无符号两种:

__device__ int __dp4a(int srcA, int srcB, int c);

__device__ int __dp4a(char4 srcA, char4 srcB, int c);

__device__ unsigned int __dp4a(unsigned int srcA, unsigned int srcB, unsigned int c);

__device__ unsigned int __dp4a(uchar4 srcA, uchar4 srcB, unsigned int c);

两个版本都假设A和B的四个向量元素被压缩到32位字的四个相应字节中。char4`/`uchar4`版本使用带有显式字段的CUDA结构类型,而包装在'int'版本中是隐式的。

如前所述,DP2A具有用于分别选择输入B的高或低两个字节的“高”和“低”版本。

// Generic [_lo]

__device__ int __dp2a_lo(int srcA, int srcB, int c);

__device__ unsigned int __dp2a_lo(unsigned int srcA, unsigned int srcB, unsigned int c);

// Vector-style [_lo]

__device__ int __dp2a_lo(short2 srcA, char4 srcB, int c);

__device__ unsigned int __dp2a_lo(ushort2 srcA, uchar4 srcB, unsigned int c);

// Generic [_hi]

__device__ int __dp2a_hi(int srcA, int srcB, int c);

__device__ unsigned int __dp2a_hi(unsigned int srcA, unsigned int srcB, unsigned int c);

// Vector-style [_hi]

__device__ int __dp2a_hi(short2 srcA, char4 srcB, int c);

__device__ unsigned int __dp2a_hi(ushort2 srcA, uchar4 srcB, unsigned int c);

请记住,基于GP102、GP104和GP106 GPU的Tesla、GeForce和Quadro加速器上提供了DP2A和DP4A,而不是Tesla P100(基于GP100 GPU)。

Download CUDA 8

要充分利用GPU上的混合精度计算,请下载免费的NVIDIA CUDA工具包版本8。要了解CUDA 8的所有强大功能,请查看后cuda8显示的功能。

cusparse下载_CUDA 8混合精度编程相关推荐

  1. CUDA 8混合精度编程

    CUDA 8混合精度编程 Mixed-Precision Programming with CUDA 8 论文地址:https://devblogs.nvidia.com/mixed-precisio ...

  2. CUDA 8的混合精度编程

    CUDA 8的混合精度编程 Volta和Turing GPU包含 Tensor Cores,可加速某些类型的FP16矩阵数学运算.这样可以在流行的AI框架内更快,更轻松地进行混合精度计算.要使用Ten ...

  3. 深入理解混合精度训练:从 Tensor Core 到 CUDA 编程

    背景 近年来,自动混合精度(Auto Mixed-Precision,AMP)技术在各大深度学习训练框架中作为一种使用简单.代价低廉.效果显著的训练加速手段,被越来越广泛地应用到算法研究中. 然而大部 ...

  4. 最高加速9倍!字节跳动开源8比特混合精度Transformer引擎

    ​ 计算机视觉研究院专栏 作者:Edison_G 近年来,Transformer 已经成为了 NLP 和 CV 等领域的主流模型,但庞大的模型参数限制了它的高效训练和推理.于是字节跳动在 2019 年 ...

  5. 【iOS与EV3混合机器人编程系列之三】编写EV3 Port Viewer 应用监测EV3端口数据

    在前两篇文章中,我们对iOS与EV3混合机器人编程做了一个基本的设想,并且介绍了要完成项目所需的软硬件准备和知识准备. 那么在今天这一篇文章中,我们将直接真正开始项目实践. ==第一个项目: EV3 ...

  6. 学术速递4 | 谷歌混合精度量化 | 清华语音人脸视频生成 | 谭铁牛步态识别对抗攻击 | 北大点云数据

    ​几篇近期的paper: 清华:音频驱动的具有自然头部姿势的语音人脸视频生成 谭铁牛:对步态识别的时间稀疏对抗性攻击 Google Brain:无需专用硬件加速的混合精度量化 北大:SemanticP ...

  7. PyTorch 单机多卡操作总结:分布式DataParallel,混合精度,Horovod)

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 作者丨科技猛兽@知乎 来源丨https://zhuanlan.zhihu.com/p/15837505 ...

  8. python单精度和双精度_单精度、双精度、多精度和混合精度计算的区别是什么?...

    点击上方"大鱼机器人",选择"置顶/星标公众号" 福利干货,第一时间送达! 编排 | strongerHuang 微信公众号 | 嵌入式专栏 我们学过数学,都知 ...

  9. 基于OpenSeq2Seq的NLP与语音识别混合精度训练

    基于OpenSeq2Seq的NLP与语音识别混合精度训练 Mixed Precision Training for NLP and Speech Recognition with OpenSeq2Se ...

最新文章

  1. fragment生命周期
  2. 手把手教你使用 1D 卷积和 LSTM 混合模型做 EEG 信号识别
  3. 你绝对能懂的“机器学习”(二)
  4. POJ1033 Defragment
  5. 卷积神经网络架构理解
  6. [Java] 蓝桥杯BASIC-30 基础练习 阶乘计算
  7. 品高云入围央采软件协议供货名单
  8. c语言超时自动退出,Golang实现for循环运行超时后自动退出的方法
  9. python web全栈工程师招聘_【笔记】Web全栈工程师的自我修养(上)
  10. 【手把手】教你MySQL调优
  11. nodejs生成pdf文件
  12. VINS-Mono 代码解析——视觉跟踪 feature_trackers
  13. 《易学C++(第2版)》——2.2 如何创建一个程序
  14. Android长图文截图的实现(支持截取第三方app)-(一)
  15. 百度-视觉技术部招聘计算机视觉相关算法实习生
  16. 深度剖析C语言结构体
  17. 内地朋友对香港银行开户的需求越发增多!
  18. 论文解析(1)——语义分割(求索ljj解读:A Review on Deep learning Techniques Applied to Semantic Segmentation)(更新中))
  19. Struts2的值栈和对象栈
  20. 【EMC专题】浪涌抗扰度测试

热门文章

  1. js 中 中文、空格、数字、字符串混合排序
  2. An adaptive gamma correction for image enhancement 低照度图像自适应gamma矫正
  3. 5OSPF的邻居和NBMA环境下的邻居
  4. java简单实现布谷鸟过滤器的
  5. docker: error pulling image configuration
  6. Rails博客软件 Enki
  7. Dep包管理的主要机制
  8. oppor15android10怎么降级,OPPOR15系统降级教程
  9. python简单算法题_python - 简单算法题 - 列表偏移
  10. 关于SQL数据表存储过程表名前缀换成dbo代码