在上期,我们讲到了图灵的故事。图灵发明的密码破译机是盟军赢得二战的得力助手,但正义的联盟战胜法西斯,最终还是依靠英雄的血肉之躯。
1941年6月22日,希特勒发动了“巴巴罗萨行动”,纠集意大利、芬兰等仆从国,出动380万军队,在3000多辆坦克和2000多架作战飞机的掩护下,从北起波罗的海,南到黑海的1800多公里的战线上对苏联发起突袭,导致苏联损失惨重,一部分加盟共和国也背离了牢不可破的联盟,沦为了纳粹的仆从国。1941年11月,德军的中央集团军群已经兵临莫斯科城下。
苏共中央总书记斯大林是一个拥有钢铁意志的人。临危不乱的斯大林决定,组织一次大阅兵以鼓舞士气,反击轴心国的侵略。
1941年11月7日,莫斯科的天空飘起了大雪。
“俄罗斯地域广淼,但我们已无路可退——我们身后就是莫斯科!”
参加完阅兵的苏军直接开上了战场。在苏军的反击下,1941年12月,德军的战线开始全面动摇,最终遭受了二战中第一次重大失败。
从此,每年在卫国战争胜利纪念日,苏联都要在红场举行盛大的阅兵式,这一传统由俄罗斯继承,一直沿袭到现在。
小H发现,阅兵式上,战士们走出整齐的方阵需要三个要素:
为了让GPU能更好地完成并发计算任务,工程师们也借鉴了这一设计思想。
我们知道,在GPU中,有成千上万的CUDA核,以TU102(Turing架构)为例:
Turing架构的TU102芯片中,有4608个CUDA Core,576个Tensor Core,72个RT Core和288个Texture Unit。它们是按什么方式组织起来的呢?
我们把上图放大,再看局部:
在Turing架构中,有72个SM(Streaming Multiple-Processor,流式多处理器)。每个SM可以划分为4个进程块,每个进程块包含了16个FP32 Core,16个int32 Core,2个Tensor Core、一个线程束调度器和一个调度单有。除了这些算术逻辑单元和控制器以外,每个进程块还有64KB的寄存器和L0指令缓存。
而在CUDA中,也有对应的几个概念:
实际上,CUDA中的这些设定是帮助程序员方便进行程序设计。在CUDA中,每个Thread对应的是GPU内部的一个CUDA Core。每个block都会在GPU的SM上常驻,而一个SM可以有多个block。
熟悉CPU内部结构的读者都知道,每个CPU内部可能有多个内核,每个内核无论是否支持超线程,都有自己的指令发射单元,并可以为2个或多个超线程发射不同的指令。但是,在GPU中并非如此。
CUDA是一种SIMT架构(单指令多线程),每个SM中只有一个指令发射单元,每个指令会发射到多个CUDA核进行并行执行。NVidia把32个Threads组成一个warp(也就是所谓的线程束),它是指令发射的最小颗粒。
与CPU类似的是,每个CUDA Core拥有自己的指令计数器,地址计数器和状态寄存器,还可以有自己的独立执行路径,而指令则由SM内部的scheduler来调度发射。
在这样的机制保障下,多个CUDA Core就可以在统一的指挥下,以Warp为最小的组织单位,步调一致地进行计算了。
这看起来是一个很优雅的设计,但又衍生了两个问题:
这两个问题我们留到下期解答。