direct90c是什么意思(directx9和11的区别)

direct90c是什么意思(directx9和11的区别)

自动驾驶、智能机器人、新材料发现、医药科学、医学影像分析…人工智能时代的科学研究极度依赖算力支持。提供算力的硬件芯片厂商中,首屈一指当属英伟达。如果不聊几句GPU和英伟达,都不好意思跟别人说自己是做人工智能的,而在人工智能领域,获得英伟达的相关认证,也是业界备受瞩目的事情,这代表了行业上游对技术、架构、赛道的肯定。

△ 右侧奖杯2020年英伟达颁发

那么,英伟达的GPU是如何加速计算呢?本系列将介绍GPU计算加速的一些基础知识:什么是GPUGPU全名为Graphics Processing Unit,又称视觉处理器、图形显示卡。GPU负责渲染出2D、3D、VR效果,主要专注于计算机图形图像领域。我们先对 GPU 有一个直观的认识,如下图:

众所周知,由于存储器的发展慢于处理器,在 CPU 上发展出了多级高速缓存的结构,如上面左图所示。而在 GPU 中,也存在类似的多级高速缓存结构。只是相比 CPU,GPU 将更多的晶体管用于数值计算,而不是缓存和流控(Flow Control)。这源于两者不同的设计目标,CPU 的设计目标是并行执行几十个线程,而 GPU 的目标是要并行执行几千个线程。可以在上面右图看到,GPU 的 Core 数量要远远多于CPU,但是有得必有失,可以看到 GPU 的 Cache 和 Control 要远远少于 CPU,这使得 GPU 的单 Core 的自由度要远远低于 CPU,会受到诸多限制,而这个限制最终会由程序承担。这些限制也使得 GPU 编程与 CPU 多线程编程有着根本区别。这其中最根本的一个区别可以在上右图中看出,每一行有多个 Core,却只有一个 Control,这代表着多个 Core 同一时刻只能执行同样的指令,这种模式也称为 SIMT (Single Instruction Multiple Threads). 这与现代 CPU 的 SIMD 倒是有些相似,但却有根本差别,本文在后面会深入细究。从 GPU 的架构出发,我们会发现,因为 Cache 和 Control 的缺失,只有计算密集与数据并行的程序适合使用 GPU。计算密集:数值计算的比例要远大于内存操作,因此内存访问的延时可以被计算掩盖,从而对 Cache 的需求相对 CPU 没那么大。数据并行:大任务可以拆解为执行相同指令的小任务,因此对复杂流程控制的需求较低。而深度学习恰好满足以上两点,即使存在比深度学习计算量更低且表达能力更强的模型,但如果不满足以上两点,都势必打不过 GPU 加持下的深度学习。GPU发展史

掀起人工智能浪潮

CPU vs GPU个人桌面电脑CPU一般只有2到8个CPU核心,数据中心的服务器上也只有20到40个左右CPU核心,GPU却有上千个核心。与CPU的核心不同,GPU的核心只能专注于某些特定的任务。知乎上有人把CPU比作大学教授,把GPU比作一个学校几千个小学生:同样是做加减法,几千个小学生所能做的计算,远比几十个大学教授要多得多。俗话说,三个臭皮匠,顶一个诸葛亮。大学教授的知识结构和个人能力远强于小学生,能独立解决复杂问题,小学生的知识有限,只能进行简单的计算。目前来看GPU在处理简单计算任务上有更大的优势,但是主要还是靠人海战术,并不能像CPU那样可以独当一面,短时间内也无法替换掉CPU。如下图所示,在整个计算机系统中,CPU起到协调管理的作用,管理计算机的主存、硬盘、网络以及GPU等各类元件。

历年GPU架构FermiFermi 是 Nvidia 在 2010 年发布的架构,引入了很多今天也仍然不过时的概念,而比 Fermi 更早之前的架构,小编也已经找不到太多资料了,所以本文从 Fermi 开始,先来一张总览。

GPU 通过 Host Interface 读取 CPU 指令,GigaThread Engine 将特定的数据从 Host Memory 中拷贝到内部的 Framebuffer 中。随后 GigaThread Engine 创建并分发多个 Thread Blocks 到多个 SM 上。多个 SM 彼此独立,并独立调度各自的多个 Thread Wraps 到 SM 内的 CUDA Cores 和其他执行单元上执行。上面这句话有几个概念解释一下:SM: 对应于上图中的 SM 硬件实体,内部有很多的 CUDA Cores;Thread Block: 一个 Thread Block 包含多个线程(比如几百个),多个 Blocks 之间的执行完全独立,硬件可以任意调度多个 Block 间的执行顺序,而 Block 内部的多个线程执行规则由程序员决定,程同时程序员可以决定一共有多少个 Blocks;Thread Warp: 32 线程为一个 Thread Warp,Warp 的调度有特殊规则,本文后面会继续深入。由于本文不是讲怎么写 CUDA,所以如果对 SM/Block 的解释仍然不明白,可以参考这一小节:??????????https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#scalable-programming-model??????????存在 16 个 SMs,每个 SM 带 32 个 Cuda Cores,一共 512 个 Cuda Cores. 这些数量不是固定的,和具体的架构和型号相关。接下来我们深入看 SM,来一张 SM 总览:

从上图可知,SM 内有 32 个 CUDA Cores,每个 CUDA Core 含有一个 Integer arithmetic logic unit (ALU)和一个 Floating point unit(FPU). 并且提供了对于单精度和双精度浮点数的 FMA 指令。SM 内还有 16 个 LD/ST 单元,也就是 Load/Store 单元,支持 16 个线程一起从 Cache/DRAM 存取数据。4 个 SFU,是指 Special Function Unit,用于计算 sin/cos 这类特殊指令。每个 SFU 每个时钟周期只能一个线程执行一条指令。而一个 Warp(32 线程)就需要执行 8 个时钟周期。SFU 的流水线是从 Dispatch Unit 解耦的,所以当 SFU 被占用时,Dispatch Unit 会去使用其他的执行单元。之前一直提到 Warp,但之前只说明了是 32 个线程,我们在这里终于开始详细说明,首先来看 Dual Warp Scheduler 的概览。

在之前的 SM 概览图以及上图里,可以注意到 SM 内有两个 Warp Scheduler 和两个 Dispatch Unit. 这意味着,同一时刻,会并发运行两个 warp,每个 warp 会被分发到一个 Cuda Core Group(16 个 CUDA Core), 或者 16 个 load/store 单元,或者 4 个 SFU 上去真正执行,且每次分发只执行一条指令,而 Warp Scheduler 维护了多个(比如几十个)的 Warp 状态。这里引入了一个核心的约束,任意时刻,一个 Warp 里的 Thread 都在执行同样的指令,对于程序员来说,观测不到一个 warp 里不同 thread 的不同执行情况。但是众所周知,不同线程可能会进入不同的分支,这时如何执行一样的指令?

可以看上图,当发生分支时,只会执行进入该分支的线程,如果进入该分支的线程少,则会发生资源浪费。在 SM 概览图里,我们可以看到 SM 内 64KB 的 On-Chip Memory,其中 48KB 作为 shared memory, 16KB 作为 L1 Cache. 对于 L1 Cache 以及非 On-Chip 的 L2 Cache,其作用与 CPU 多级缓存结构中的 L1/L2 Cache 非常接近,而 Shared Memory,则是相比 CPU 的一个大区别。无论是 CPU 还是 GPU 中的 L1/L2 Cache,一般意义上都是无法被程序员调度的,而 Shared Memory 设计出来就是让渡给程序员进行调度的片上高速缓存。Kepler2012 年 NVIDIA 发布了 Kepler 架构,我们直接看使用 Kepler 架构的 GTX680 概览图:

可以看到,首先 SM 改名成了 SMX,但是所代表的概念没有大变化,我们先看看 SMX 的内部:

还是 Fermi 中熟悉的名词,就是数量变多了很多。本人认为这个 Kepler 架构中最值得一提的是 GPUDirect 技术,可以绕过 CPU/System Memory,完成与本机其他 GPU 或者其他机器 GPU 的直接数据交换。毕竟在 2021 年的当今,Bypass CPU/OS 已经是最重要加速手段之一。Maxwell2014 年 NVIDIA 发布了 Maxwell 架构,我们直接看架构图:

可以看到,这次的 SM 改叫 SMM 了,Core 更多了,也更强大了,这里就不过多介绍了。Pascal2016 年 NVIDIA 发布了 Pascal 架构,这是第一个考虑 Deep Learning 的架构,也是一个值得大书笔墨的架构,首先看如下图 P100。

可以看到,还是一如既往地增加了很多 Cores, 我们细看 SM 内部:

单个 SM 只有 64 个 FP32 Cuda Cores,相比 Maxwell 的 128 和 Kepler 的 192,这个数量要少很多,并且 64 个 Cuda Cores 分为了两个区块。需要注意的是,Register File 的大小并未减少,这意味着每个线程可以使用的寄存器更多了,而且单个 SM 也可以并发更多的 thread/warp/block. 由于 Shared Memory 并未减少,同样意味着每个线程可以使用的 Shared Memory 及其带宽都会变大。增加了 32 个 FP64 Cuda Cores, 也就是上图的 DP Unit. 此外 FP32 Cuda Core 同时具备处理 FP16 的能力,且吞吐率是 FP32 的两倍,这却是为了 Deep Learning 准备的了。这个版本引入了一个很重要的东西:NVLink。随着单 GPU 的计算能力越来越难以应对深度学习对算力的需求,人们自然而然开始用多个 GPU 去解决问题。从单机多 GPU 到多机多 GPU,这当中对 GPU 互连的带宽的需求也越来越多。多机之间,采用 InfiniBand 和 100Gb Ethernet 去通信,在单机内,特别是从单机单 GPU 到达单机 8GPU 以后,PCIe 的带宽往往就成为了瓶颈。为了解决这个问题,NVIDIA 提供了 NVLink 用以单机内多 GPU 内的点到点通信,带宽达到了 160GB/s, 大约 5 倍于 PCIe 3 x 16. 下图是一个典型的单机 8 P100 拓扑。

一些特殊的 CPU 也可以通过 NVLink 与 GPU 连接,比如 IBM 的 POWER8。Volta2017 年 NVIDIA 发布了 Volta 架构,这个架构可以说是完全以 Deep Learning 为核心了,相比 Pascal 也是一个大版本。首先还是一如既往地增加了 SM/Core, 我们就直接看单个 SM 内部吧。

和 Pascal 的改变类似,到了 Volta,直接拆了 4 个区块,每个区块多配了一个 L0 指令缓存,而 Shared Memory/Register File 这都没有变少,也就和 Pascal 的改变一样,单个线程可使用的资源更多了。单个区块还多个两个名为 Tensor Core 的单元,这就是这个版本的核心了。可以吐槽一下,这个版本又把 L1 和 Shared Memory 合并了。我们首先看 CUDA Core, 可以看到,原本的 CUDA Core 被拆成了 FP32 Cuda Core 和 INT32 Cuda Core,这意味着可以同时执行 FP32 和 INT32 的操作。众所周知,DeepLearning 的计算瓶颈在矩阵乘法,在 BLAS 中称为 GEMM,TensorCore 就是只做 GEMM 计算的单元,可以看到,从这里开始,NVIDIA 从 SIMT 走到了 SIMT DSA 的混合。每个 TensorCore 只做如下操作:D=A*B C即:

其中 A, B, C, D 都是 4×4 的矩阵,且 A 和 B 是 FP16 矩阵,C 和 D 可以是 FP16 或者 FP32. 通常,更大的矩阵计算会被拆解为这样的 4×4 矩阵乘法。这样的矩阵乘法是作为 Thread Warp 级别的操作在 CUDA 9 开始暴露给程序员,除此以外,使用 cublas 和 cudnn 当然同样也会在合适的情况下启用 TensorCore.在这个版本中,另一个重要更新是 NVLink, 简单来说就是更多更快。每个连接提供双向各自 25GB/s 的带宽,并且一个 GPU 可以接 6 个 NVLink,而不是 Pascal 时代的 4 个。一个典型的拓扑如下图:

从 Volta 开始,线程调度发生了变化,在 Pascal 以及之前的 GPU 上,每个 Warp 里的 32 个线程共享一个 Program Counter (简称 PC) ,并且使用一个 Active Mask 表示任意时刻哪些线程是可运行的,一个经典的运行如下:

直到第一个分支完整结束,才会执行另一个分支。这意味着同一个 warp 内不同分支失去了并发性,不同分支的线程互相无法发送信号或者交换数据,但同时,不同 warp 之间的线程又保留了并发性,这当中的线程并发存在着不一致,事实上如果程序员不注意这点,很可能导致死锁。在 Volta 中解决了这个问题,同 warp 内的线程有独立的 PC 和栈,如下:

由于运行时仍然要符合 SIMT,所以存在一个调度优化器负责将可运行的线程分组,使用 SIMT 模式执行。经典运行如下:

上图可以注意到,Z 的执行并没有被合并,这是因为 Z 可能会产生一些被其他分支需要的数据,所以调度优化器只有在确定安全的情况下才会合并 Z,所以上图 Z 未合并只是一种情况,一般来说,调度优化器足够聪明可以发现安全的合并。程序员也可以通过一个 API 来强制合并,如下:

从 Volta 开始,提高了对多进程并发使用 GPU 的支持。在 Pascal 及之前,多个进程对单一 GPU 的使用是经典的时间片方式。从 Volta 开始,多个用不满 GPU 的进程可以在 GPU 上并行,如下图:

Turing2018 年 NVIDIA 发布了 Turing 架构,个人认为是 Volta 的延伸版本,当然首先各种参数加强,不过我们这里就不提参数加强了。

这里面最核心的升级就是 Tensor Core 了。除了在 Volta 中的 FP16 以及在 Turing 中的 INT8/INT4/Binary,这个版本新加入了 TF32, BF16, FP64 的支持。着重说说 TF32 和 BF16, 如下图:

FP16 的问题在于表示范围不够大,在梯度计算时容易出现 underflow, 而且前后向计算也相对容易出现 overflow, 相对来说,在深度学习计算里,范围比精度要重要得多,于是有了 BF16,牺牲了精度,保持和 FP32 差不多的范围,在此前比较知名支持 BF16 的就是 TPU. 而 TF32 的设计,在于即汲取了 BF16 的好处,又保持了一定程度对主流 FP32 的兼容,FP32 只要截断就是 TF32 了。先截断成 TF32 计算,再转成 FP32, 对历史的工作几乎无影响,如下图:

另一个变化则是细粒度的结构化稀疏,深度学习模型压缩这个领域除了量化,稀疏也是一个大方向,只是稀疏化模型难以利用硬件加速,这个版本的 GPU 则为稀疏提供了一些支持,当前的主要目的则是应用于 Inference 场景。首先说 NVIDIA 定义的稀疏矩阵,这里称为 2:4 的结构化稀疏,2:4 的意思是每 4 个元素当中有 2 个值非 0,如下图:

首先使用正常的稠密 weight 训练,训练到收敛后裁剪到 2:4 的结构化稀疏 Tensor,然后走 fine tune 继续训练非 0 的 weight, 之后得到的 2:4 结构化稀疏 weight理想情况下具有和稠密 weight 一样的精确度,然后使用此稀疏化后的 weight 进行 Inference. 而这个版本的 TensorCore 支持一个 2:4 的结构化稀疏矩阵与另一个稠密矩阵直接相乘。最后一个比较重要的特性就是 MIG(Multi-Instance GPU)了,虽然业界的计算规模确实越来越大,但也存在不少的任务因为其特性导致无法用满 GPU 导致资源浪费,所以存在需求在一个 GPU 上跑多个任务,在这之前有些云计算厂商会提供虚拟化方案。而在安培中,会为此需求提供支持,称为 MIG.可能会有人有疑问,在 Volta 中引入的多进程支持不是解决了问题吗?举个例子,在 Volta 中,虽然多个进程可以并行,但是由于所有进程都可以访问所有的内存资源,可能存在一个进程把所有的 DRAM 带宽占满影响到其他进程的运行,而这些被影响的进程很可能有 Throughput/Latency 要求。所以我们需要更严格的隔离。而在安培 MIG 中,每个 A100 可以被分为 7 个 GPU 实例被不同的任务使用。每个实例的 SMs 有独立的内存资源,可以保证每个任务有符合预期的稳定的 Throughput/Latency. 用户可以将这些虚拟的 GPU 实例当成真实的 GPU 使用。

△ Telsa V100单个SM设计图NVLink可以连接CPU和GPUIntel的CPU目前不支持NVLink,只能使用PCI-E技术,如下图所示。NVLink和PCI-E都是总线技术的一种。

目前Intel的CPU只能使用PCI-E与GPU通信由于CPU和GPU是分开的,在英伟达的设计理念里,CPU和主存被称为Host,GPU被称为Device。Host和Device概念会贯穿整个英伟达GPU编程。以上结构也被称为异构计算:使用CPU GPU组合来加速计算。世界上顶尖的数据中心和超级计算机均采用了异构计算架构。例如超越天河2号成为世界第一的超级计算机Summit使用了9216个IBM POWER9 CPU和27648个英伟达Tesla GPU。

软件生态英伟达能够在人工智能时代成功,除了他们在长期深耕显卡芯片领域,更重要的是他们率先提供了可编程的软件架构。2007年,英伟达发布了CUDA编程模型,软件开发人员从此可以使用CUDA在英伟达的GPU上进行并行编程。在此之前,GPU编程并不友好。CUDA简单到什么程度?有经验的程序员经过半天的培训,掌握一些基础概念后,能在半小时内将一份CPU程序修改成为GPU并行程序。

△ 英伟达软件栈继CUDA之后,英伟达不断丰富其软件技术栈,提供了科学计算所必须的cuBLAS线性代数库,cuFFT快速傅里叶变换库等,当深度学习大潮到来时,英伟达提供了cuDNN深度神经网络加速库,目前常用的TensorFlow、PyTorch深度学习框架的底层大多基于cuDNN库。英伟达能在人工智能时代击败Intel、AMD等强大对手,很大一部分是因为它丰富的软件体系。这些软件工具库使研发人员专注于自己的研发领域,不用再去花大量时间学习GPU底层知识。CUDA对于GPU就像个人电脑上的Windows、手机上的安卓系统,一旦建立好生态,吸引了开发者,用户非常依赖这套软件生态体系。GPU编程可以直接使用CUDA的C/C 版本进行编程,也可以使用其他语言包装好的库,比如Python可使用Numba库调用CUDA。慧维智能深耕多年动态医学影像AI技术,提供消化内镜辅助诊断产品內镜“帧探”。产品技术的解决方案也是基于英伟达CUDA技术;通过慧维智能资深医务团队收集、梳理海量“金标准”的数据,邀请高年资消化科医生精心标注数据集;AI技术帮助医生实现结肠疾病和结肠癌的早期诊断,并提供內镜手术中智能识别、标注、提醒和导航等功能。文献参考:https://zhuanlan.zhihu.com/p/413145211https://images.nvidia.com/aem-dam/en-zz/Solutions/geforce/ampere/pdf/NVIDIA-ampere-GA102-GPU-Architecture-Whitepaper-V1.pdfhttps://images.nvidia.com/aem-dam/en-zz/Solutions/design-visualization/technologies/turing-architecture/NVIDIA-Turing-Architecture-Whitepaper.pdfhttps://images.nvidia.com/content/volta-architecture/pdf/volta-architecture-whitepaper.pdfhttps://images.nvidia.com/content/pdf/tesla/whitepaper/pascal-architecture-whitepaper.pdfhttps://www.microway.com/download/whitepaper/NVIDIA_Maxwell_GM204_Architecture_Whitepaper.pdfhttps://www.nvidia.com/content/PDF/product-specifications/GeForce_GTX_680_Whitepaper_FINAL.pdfhttp://www.hardwarebg.com/b4k/files/nvidia_gf100_whitepaper.pdfhttps://developer.nvidia.com/content/life-triangle-nvidias-logical-pipelinehttps://blog.nowcoder.net/n/4dcb2f6a55a34de9ae6c9067ba3d3bfbhttps://jcf94.com/2020/05/24/2020-05-24-nvidia-arch/https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.htmlhttps://en.wikipedia.org/wiki/Bfloat16_floating-point_format

WillZhang

皮皮鲁的AI星球

tomoyazhang

TechSugar

关于慧维智能 慧维智能医疗科技有限公司成立于2019年6月,专业从事智能医疗产品的研发、生产与销售。我们的核心成员,均来自全球顶尖的科研机构和世界五百强企业。慧维智能以在“人工智能”和“边缘计算”领域的自主核心技术为驱动力,致力于为全球医疗机构提供“高水准、好体验”的医疗产品与服务,最大程度地帮助医生提高诊疗水平与效率。

发表评论

登录后才能评论