在上期,我们介绍了代号为GK110的NVIDIA图形核心的规格和架构设计方面的内容。在这个史无前例的巨兽面前,之前所有的GPU设计都似乎黯淡了下来,超大规模的晶体管和无与伦比的规格参数,都让玩家对GK110充满了好奇。当然,除了硬件规格上的强悍外,GK110还带来了诸多新奇和震撼的功能。
就像上期介绍GK110规格时所说的那样,在GK110首次公开的信息中基本上不包含对其图形和游戏性能方面的介绍。因为从NVIDIA的设计思路来看,GK110将像首款Fermi产品GF100那样,除了具备超强的游戏性能之外,还是一颗面向高性能计算的GPGPU。可以说,GK110一大目的就是利用自己超强的架构、规模和功能设计,帮助NVIDIA在未来的高性能计算市场占据重要地位。因此,NVIDIA针对目前GPU并行计算中存在的问题进行了一些改进,并带来了部分新的功能。下面本文就对GK110的重要功能一一进行介绍。
在传统的GPU-CPU的计算架构中,CPU往往用于控制、逻辑处理等,自己贡献的计算能力不多,GPU则会利用大规模并行计算能力提供强大的计算性能。在这种系统中,GPU需要在CPU的控制下才可以运作。
NVIDIA给出的动态并行控制的示意图,可见在kepler上,CPU的工作被大大简化了。
NVIDIA给出有关动态并行控制的实例图。三幅图片中,左边的一副图片是低精度,但是速度快;中间的是高精度,但是速度很慢;右边图片展示的的是自动控制,在右边图片的左侧变化较小的部分使用低精度,图片右侧变化较快的部分使用高精度,既保证了计算进度又兼顾了效能。
在Fermi执行程序的过程中,任何一个任务都是由CPU分发给GPU,GPU执行完成后再告诉CPU,然后CPU再给GPU新的任务。举例来说,A任务执行完成后,如果结果为真,那么执行B任务,否则执行C任务。这是一个简单的条件判断。一般用类似“if……else……”的语句来处理。在Fermi上,这个任务的执行过程是这样:
1.CPU分配A任务给GPU,GPU执行计算并完成计算。
2.GPU请求CPU判定,CPU判定结果为真(或者假)。
3.CPU指定GPU处理B(或者C)任务,GPU执行计算并完成计算。
4.GPU向CPU报告任务完成,等待CPU确认。
5.CPU分配下一个计算任务给GPU。
Fermi拥有很不错的并行计算能力,但无法处理类似的判断语句。用“正规”一些的语言来描述,也就是说,在CUDA执行中,Femri的任何一个Kernel只能由CPU给予,自己基本无法执行判断和逻辑操作,即使这个逻辑非常简单。Kernel是CUDA的专用数据,汉译为“核心、要点”,在CUDA中,在GPU上执行的程序或者计算,可以被称之为kernel。
这种GPU和CPU的紧密相关性,让CPU在很多情况下占用率变高,对CPU的性能也有一定要求。实际上这种简单的判定工作需要的处理电路并不复杂,于是在GK110上,动态并行控制的加入,让GPU在执行类似语句时有了判定的能力。
我们依旧用上面的例子来打比方。在上述过程中,对CPU来说,很大部分时间都用于帮GPU做判定、给GPU指派任务。拥有动态并行控制后,上述流程将变为:
1.CPU给GPU任务A。
2.GPU处理A,然后自动判定,并生成新的任务,自动处理C或者B。
3.GPU报告CPU处理完成。
这样的过程变得更为清晰简单,在整个流程中,CPU只需要关心开始和结束,对中间的内容几乎不需要参与。这可以节约大部分CPU的工作量,让CPU去进行更复杂的任务或者干脆使用一颗性能较低的CPU即可完成。此外,动态并行控制可以让GPU在同时间内启动更多的计算进程,并且能够自我判断、自动控制计算,也能为程序人员节约大量的时间。
NVIDIA给出了一个例子展示动态并行控制的计算方式。在对一些流体或者热量的计算中,为了取得比较合理的数据,通常要么使用一个比较粗的计算粒度来获得比较宽泛的数据,这样对GPU来说计算压力很小,但精度不够;要么使用极为精细的计算粒度来获得精确数据,但这样对GPU的性能压力又太大了。因为GPU不能动态进行并行控制,并且不能自己指定计算kernel,因此只能机械地以某种固定的值来进行计算。对程序编制人员来说,找出一个合适的值,来既保证精确度,又保证GPU不会由于计算强度过高而浪费时间,也是一件颇为头疼的事情。
在动态流程控制启用后,这样的事情就变得简单多了。程序员可以制定命令,让GPU自己去判断是否需要更高的计算精度。在NVIDIA的例子中,左侧的部分变化很小,因此不需要经常刷新、计算要求不高,但越往右侧,变化越频繁,越需要更精确的计算。在这种情况下,GPU可以自动判断左侧的部分并使用低精度计算,右侧计算精度则高一些。这样既可以节约计算能力,又能获得需要的计算精度。