部落格版本:
http://dorgon.horizon-studio.net/zh/archives/1805
在研究ISPC的时候发现这东西谜团有点多,因此花了一些时间做了研究并写成文章
分享给大家
本文开始
SIMD(Single Instruction Multiple Data)指的是用一个指令同时处理多个资料这个概念
,只是我们常常被误导说,在CPU上可以使用SIMD指令来加速──这种说法其实并不精确
。对,我就是被误导的那个。在UE4.23时官方整合了ISPC,以更好的帮助CPU做平行化加
速,我之前一直把这东西跟SIMD画上等号,没去仔细思考这东西的存在到底想解决什么问
题。
根据指令数跟跟资料的处理方式,这个概念其实是根据Flynn’s Taxonomy来进行分类,
而SIMD只是其中一种。 见: https://zh.wikipedia.org/zh-mo/%E8%B2%BB%E6%9E%97%E5%88%86%E9%A1%9E%E6%B3%95
SIMD就现行的计算机架构上,分为以下三种:
Vector Architecture:这个架构在以前是是超级电脑的代名词,最常在教科书上提到的
是1975年的Cray-1,第一个使用这个架构的计算机。
Multimedia SIMD Instruction set extension:看名字就可以知道,它的目的是针对多
媒体应用的ISA的扩充指令集,例如图像、影片等等影音需求。基本上是架构在Scalar
Processor之上的扩充。
GPU:这个比较好理解,他在架构上有点像是Vector Architecture,但有些微妙的不同。
不过由于Vector Architecture在商业竞争上输给了Intel因此逐渐式微,以Scalar
Processor为主的设计主宰了过去将近30~40年的时间。输掉的原因有很多,但主要并不是
技术问题,而是那个时代大部份的人不需要那么强的计算力,客户太少,再加上摩尔定律
的推波助澜下,人们的注意力自然就只集中在由Intel主推拥有最多客户的架构上。然而
近来由于AI时代的来临,Vector Architecture架构又重新回到了人们眼界中了,例如
google tensor里面的TPU就包含了Vector processor,以及最近很火红的RISC-V,由于设
想目标是embedded devices,不像个人电脑需要考虑兼容性,因此可以大胆的抛弃旧包袱
,转而使用相关的Vector Operation指令。
另一方面,关于Multimedia SIMD,主要是由于Intel在网络起飞的时代发现我们基于
Scalar Processor的架构还是需要Vector Architecture那种一个指令同时处理多个资料
的加速能力,因此他的解决方式非常粗暴,就是加入新的register跟指令集的方式来支援
这个概念。不过当我们开始叠加register跟指令集之后就开始失控了,每我们加一组新的
register,我们就要追加一堆新的指令集来支援相关Vector操作,从XMM(128 bit)、
YMM(256 bit)到ZMM(512 bit)。这些指令集的扩充非常快速,从1996年开始,几乎每2~3
年就有新的特性加入,然而为了兼容性,新的指令集在加入x86系统后就非常难被移除,
因此现代指令集暴增的这么快速有很大的原因可以归究于Multimedia SIMD的发展。
接下来让我们来稍微看一下这些扩充指令集,感受一下它发展的混乱吧:从1996年的MMX
,它总共有57条扩充指令使用,到SSE又追加了70条,接着SSE2加入了144条指令,而SSE3
只是在原有架构下的扩充,所以只追加了13条指令。接下来则是SSE4.1跟4.2,又分别加
入了47条跟7条。前面的架构使用到的是XMM register,接下来为了增加平行化的数量,
Intel推出了AVX系列,使用的是YMM register,然后又更进一步的推出了AVX-512,使用
ZMM register。可惜的是我目前没找到AVX的指令集数量,不过我猜应该有上百个。问了
一下AI,他是跟我说要看所使用的具体版本。
对于最新的AVX512,Linus Torvalds在2020年的时曾经破口大骂说:我希望AVX-512可以
死的痛苦一点(I hope AVX512 dies a painful death)。希望intel不要靠增加魔法指令
来让跑分好看,要他们回到正轨。
基本上这玩意耗能大,大部份的人享受不到好处,又不是什么科研计算,也不是server,
一般人在使用电脑的时候又常常需要切换process执行,这代表作业系统会不断的进行
Context Switch,要知道,每次Context Switch是需要把当前计算用到的register保存下
来,在这一读一写之间很容易让使用者感受到延迟,而且还多占了空间。
另外在Intel 12th Gen CPU他设计了二种不同架构的P跟E Core,这是常见的大小核架构
,只是小核不支援AVX- 512,没办法相容的结果Intel就干脆把这东西关掉了,虽然能修
改BIOS把这东西开回来,不过看起来有点麻烦。这玩意目前看起来确实是半残了,今年的
13代一样延续同样的架构因此不支援AVX512,不知道这指令会不会如Linus所期望的痛苦
的死去,就让我们看下去。不过令人意外的是AMD Zen 4之后的CPU倒是支援这套指令集的
。
对于我们程式设计师而言,非常痛苦的是,每次有追加新的指令集我们都需要手动去
include相关的header档,然后额外针对新的指令撰写新的程式。
见:
https://stackoverflow.com/questions/11228855/header-files-for-x86-simd-intrinsics
有了以上知识,我们回头来看Intel ISPC就可很清楚的掌握这技术到底想解决什么问题了
。在官网上这技术的定义是SPMD(single program, multiple data),就是说我们只要像
GPU写Shader Code一样,我们只要部份C++ code用ispc专用的script改写成一段“
program”存成.ispc这个档案,在编译阶段它就会自动帮我们把这个档案拉进去转成目标
指令集的样子,这样子的话,当有新的指令集被加入后,我们只需要重新编译程式就行,
而不需要再去改写程式。当然,还要重新编译新程式这点还是蛮烦人的,不过这个就是扩
充指令集的原罪。
根据Epic官方在Siggraph2019的演讲,目前ISPC主要是用在Animation跟Chaos这二个系统
上,在部份关键的程式码上大约会有3倍左右的性能提升。不过需要注意的是,在使用
ISPC后,那些程式片段没办法享受到PGO(Profile-Guided Optimization)带来的效能提升
。
见:Causing Chaos: Physics and Destruction in UE4 | SIGGRAPH 2019 | Unreal
Engine https://www.youtube.com/watch?v=y2QIpPTv6yU
参考:
Linux之父怒骂Intel AVX-512:“我希望它死得痛苦点...”
https://news.xfastest.com/others/82781/linus-torvalds-i-hope-intels-avx-512-dies-a-painful-death/
硬科技:浅谈x86的SIMD指令扩张史(上):MMX到SSE
https://www.cool3c.com/article/152918
RISC-V Vector Instructions vs ARM and x86 SIMD
https://medium.com/swlh/risc-v-vector-instructions-vs-arm-and-x86-simd-8c9b17963a31
从 Pentium 回顾 x86 处理器到底哪里难做
https://blog.moneydj.com/news/2020/10/02/%E5%BE%9E-pentium-%E5%9B%9E%E9%A1%A7-x86-%E8%99%95%E7%90%86%E5%99%A8%E5%88%B0%E5%BA%95%E5%93%AA%E8%A3%A1%E9%9B%A3%E5%81%9A/