● shared:统一带来的阵痛
我们前面曾经提到过,草稿纸其实也是一种缓冲。既然说到了草稿纸,你还记得小学时做一道应用题需要多少草稿纸么?我估计一张A4纸大小的草稿纸就足够一个哪怕是拥有毕加索一般的天赋,能够边算边涂鸦的小学生完成一次数学期末考试了。那你还记得大学以后做一道题需要多少草稿纸么?我记得研一那年某次做数学物理方程的作业,一道题就让我用掉了9页A4纸,而那次作业有9道题,害得我不得不跑去实验室偷了半包打印纸回来……
毕业5年后仍然让笔者看得心惊肉跳的弦振动方程
这现象说明了一个并不复杂的问题——随着运算量、运算难度以及运算通用度的增加,运算单元所需要的缓存量也是会大幅增长的。
伴随着DirectX 10对shader单元的统一,ALU成了整个GPU的核心部分。过去VS和PS单元会分别处理矢量和标量数据,而shader统一之后,同一个ALU必须同时面对向量和标量数据。再加上直接向程序员开放ALU带来的通用计算需求,伴随着由此带来的执行环境以及编程环境的改变,ALU所要面对的运算种类和通用性都有了很大的改变,其作为常规的通用运算资源所需要的缓冲量也便跟着大幅增加了。
为了应付全新的缓冲需求,同时也为程序能够更高效率的得到执行,微软在DirectX 10中第一次引入了shared的概念。shared是一组面向ALU开放的延迟完全透明的只读cache,ALU可以将需要的数据临时寄存在这里。shared只读不可写,因此并不能与延迟不透明的unified cache相提并论,但对于线程、图形指令和大多数需要几何关联的传统通用计算指令来说,shared已经可以满足要求了。
相比于显存和纹理缓存,shared的年纪要小很多很多,它也是缓冲体系中最后出现的一位。第一个引入硬件shared的构架是NVIDIA的G80,G80为每一个SM中的8个SP(ALU)单元配备了16K的shared memory,每个SP均可以访问全部的shared bank,这种富足的资源设计一直维持到GT200为止。AMD在R600中也引入了名为GDS(Golbal Data Share)的shared机制,以便满足对DirectX 10的基本支持,由于GDS本身的不完善,AMD又在此后的RV770中再次引入了LDS(Local Data Share)这一2级shared作为GDS的补充,并最终在RV870中完善了LDS的功能,使其可以发挥出应有的性能。
shared的出现为ALU提供了较好的临时缓冲空间,客观上提升了处理shader及通用计算指令的效率,但这种做法让好不容易看到了统一希望的缓冲体系再度凭添了新的混乱因素。NVIDIA的构架因为shared的引入而变成了shared memory和L1/L2 Texture cache分离并各事其主的状态,实际上与统一Texture cache之前并没有本质区别。而承袭ATI专缓专用衣钵的AMD则更是创造了GDS+LDS+shader constant cache+shader instruction cache+memory R/W cache+L1/L2 Texture cache+Z cache+Stencil cache+color cache+……好吧,我不知道该怎么形容了……的混乱状态。尽管这其中有不少工作实际上是使用register来进行的,但最低限度下2级shared的出现确实在事实上影响了程序员对硬件的使用以及AMD对自身硬件的控制……
可怜的程序员们以及更加可怜的用户们,难道就只能接受这么乱下去的现状了么?