Blog

什么是ASIC

Content #

除了 CPU、GPU,以及刚刚的 FPGA,我们其实还需要用到很多其他芯片。比如,现在手机里就有专门用在摄像头里的芯片;录音笔里会有专门处理音频的芯片。尽管一个 CPU 能够处理好手机拍照的功能,也能处理好录音的功能,但是我们直接在手机或者录音笔里塞上一个 Intel CPU,显然比较浪费。

于是,我们就考虑为这些有专门用途的场景,单独设计一个芯片。这些专门设计的芯片呢,我们称之为 ASIC(Application-Specific Integrated Circuit),也就是专用集成电路。事实上,过去几年,ASIC 发展得特别快。因为 ASIC 是针对专门用途设计的,所以它的电路更精简,单片的制造成本也比 CPU 更低。而且,因为电路精简,所以通常能耗要比用来做通用计算的 CPU 更低。而我们上一讲所说的早期的图形加速卡,其实就可以看作是一种 ASIC。

因为 ASIC 的生产制造成本,以及能耗上的优势,过去几年里,有不少公司设计和开发 ASIC 用来“挖矿”。这个“挖矿”,说的其实就是设计专门的数值计算芯片,用来“挖”比特币、ETH 这样的数字货币。

Viewpoints #

From #

32 | FPGA和ASIC:计算机体系结构的黄金时代

什么是FPGA

Content #

FPGA,也就是现场可编程门阵列(Field-Programmable Gate Array)。看到这个名字,你可能要说了,这里面每个单词单独我都认识,放到一起就不知道是什么意思了。

没关系,我们就从 FPGA 里面的每一个字符,一个一个来看看它到底是什么意思。

  1. P 代表 Programmable,这个很容易理解。也就是说这是一个可以通过编程来控制的硬件。

  2. G 代表 Gate 也很容易理解,它就代表芯片里面的门电路。我们能够去进行编程组合的就是这样一个一个门电路。

  3. A 代表的 Array,叫作阵列,说的是在一块 FPGA 上,密密麻麻列了大量 Gate 这样的门电路。

  4. 最后一个 F,不太容易理解。它其实是说,一块 FPGA 这样的板子,可以在“现场”多次进行编程。它不像 PAL(Programmable Array Logic,可编程阵列逻辑)这样更古老的硬件设备,只能“编程”一次,把预先写好的程序一次性烧录到硬件里面,之后就不能再修改了。

这么看来,其实“FPGA”这样的组合,基本上解决了我们前面说的想要设计硬件的问题。我们可以像软件一样对硬件编程,可以反复烧录,还有海量的门电路,可以组合实现复杂的芯片功能。

Viewpoints #

From #

32 | FPGA和ASIC:计算机体系结构的黄金时代

统一着色器架构(Unified Shader Architecture)

Content #

可编程管线(Programable Function Pipeline)时候的 GPU,有两类 Shader,也就是 Vertex Shader 和 Fragment Shader。在进行顶点处理的时候,我们操作的是多边形的顶点;在片段操作的时候,我们操作的是屏幕上的像素点。对于顶点的操作,通常比片段要复杂一些。所以一开始,这两类 Shader 都是独立的硬件电路,也各自有独立的编程接口。因为这么做,硬件设计起来更加简单,一块 GPU 上也能容纳下更多的 Shader。

不过呢,大家很快发现,虽然我们在顶点处理和片段处理上的具体逻辑不太一样,但是里面用到的指令集可以用同一套。而且,虽然把 Vertex Shader 和 Fragment Shader 分开,可以减少硬件设计的复杂程度,但是也带来了一种浪费,有一半 Shader 始终没有被使用。在整个渲染管线里,Vertext Shader 运行的时候,Fragment Shader 停在那里什么也没干。Fragment Shader 在运行的时候, Vertext Shader 也停在那里发呆。

本来 GPU 就不便宜,结果设计的电路有一半时间是闲着的。喜欢精打细算抠出每一分性能的硬件工程师当然受不了了。于是,统一着色器架构(Unified Shader Architecture)就应运而生了。

既然大家用的指令集是一样的,那不如就在 GPU 里面放很多个一样的 Shader 硬件电路,然后通过统一调度,把顶点处理、图元处理、片段处理这些任务,都交给这些 Shader 去处理,让整个 GPU 尽可能地忙起来。这样的设计,就是我们现代 GPU 的设计,就是统一着色器架构。

有意思的是,这样的 GPU 并不是先在 PC 里面出现的,而是来自于一台游戏机,就是微软的 XBox 360。后来,这个架构才被用到 ATI 和 NVidia 的显卡里。这个时候的“着色器”的作用,其实已经和它的名字关系不大了,而是变成了一个通用的抽象计算模块的名字。

正是因为 Shader 变成一个“通用”的模块,才有了把 GPU 拿来做各种通用计算的用法,也就是 GPGPU(General-Purpose Computing on Graphics Processing Units,通用图形处理器)。而正是因为 GPU 可以拿来做各种通用的计算,才有了过去 10 年深度学习的火热。

...

着色器(Shader)

Content #

可编程管线(Programable Function Pipeline) 这些可以编程的接口,我们称之为 Shader,中文名称就是着色器。之所以叫“着色器”,是因为一开始这些“可编程”的接口,只能修改顶点处理和片段处理部分的程序逻辑。我们用这些接口来做的,也主要是光照、亮度、颜色等等的处理,所以叫着色器。

From #

可编程管线(Programable Function Pipeline)

Content #

程序员希望我们的 GPU 能有一定的可编程能力。这个编程能力不是像 CPU 那样,有非常通用的指令,可以进行任何你希望的操作,而是在整个的渲染管线(Graphics Pipeline)的一些特别步骤,能够自己去定义处理数据的算法或者操作。于是,从 2001 年的 Direct3D 8.0 开始,微软第一次引入了可编程管线(Programable Function Pipeline)的概念。

早期的可编程管线的 GPU,提供了单独的顶点处理和片段处理(像素处理)的着色器

一开始的可编程管线呢,仅限于顶点处理(Vertex Processing)和片段处理(Fragment Processing)部分。比起原来只能通过显卡和 Direct3D 这样的图形接口提供的固定配置,程序员们终于也可以开始在图形效果上开始大显身手了。

Viewpoints #

From #

31 | GPU(下):为什么深度学习需要使用GPU?

像素操作(Pixel Operations)

Content #

我们就要把不同的多边形的像素点“混合(Blending)”到一起。可能前面的多边形可能是半透明的,那么前后的颜色就要混合在一起变成一个新的颜色;或者前面的多边形遮挡住了后面的多边形,那么我们只要显示前面多边形的颜色就好了。最终,输出到显示设备。

Viewpoints #

From #

30 | GPU(上):为什么玩游戏需要使用GPU?

栅格化(Rasterization)

Content #

我们的屏幕分辨率是有限的。它一般是通过一个个“像素(Pixel)”来显示出内容的。所以,对于做完图元处理的多边形,我们要开始进行第三步操作。这个操作就是把它们转换成屏幕里面的一个个像素点。这就叫作栅格化。这个栅格化操作,有一个特点和上面的顶点处理是一样的,就是每一个图元都可以并行独立地栅格化。

Viewpoints #

From #

30 | GPU(上):为什么玩游戏需要使用GPU?

图元处理(Primitive Processing)

Content #

图元处理,其实就是要把顶点处理完成之后的各个顶点连起来,变成多边形。其实转化后的顶点,仍然是在一个三维空间里,只是第三维的 Z 轴,是正对屏幕的“深度”。所以我们针对这些多边形,需要做一个操作,叫剔除和裁剪(Cull and Clip),也就是把不在屏幕里面,或者一部分不在屏幕里面的内容给去掉,减少接下来流程的工作量。

Viewpoints #

From #

30 | GPU(上):为什么玩游戏需要使用GPU?

顶点处理(Vertex Processing)

Content #

图形渲染的第一步是顶点处理。构成多边形建模的每一个多边形呢,都有多个顶点(Vertex)。这些顶点都有一个在三维空间里的坐标。但是我们的屏幕是二维的,所以在确定当前视角的时候,我们需要把这些顶点在三维空间里面的位置,转化到屏幕这个二维空间里面。这个转换的操作,就被叫作顶点处理。

如果你稍微学过一点图形学的话,应该知道,这样的转化都是通过线性代数的计算来进行的。可以想见,我们的建模越精细,需要转换的顶点数量就越多,计算量就越大。而且,这里面每一个顶点位置的转换,互相之间没有依赖,是可以并行独立计算的。

顶点处理就是在进行线性变换

Viewpoints #

From #

30 | GPU(上):为什么玩游戏需要使用GPU?