1
本文作者: 矽說(shuō) | 2016-12-20 13:15 |
雷鋒網(wǎng)按:本文作者癡笑,矽說(shuō)(微信號(hào):silicon_talks)主筆。本文為《腦芯編:窺腦究竟,織網(wǎng)造芯》系列第四篇。
寫這篇的時(shí)候想到哥哥的《我》,因?yàn)檫@次的主角就是,那個(gè)特里獨(dú)行的我:
我就是我,是長(zhǎng)度不一樣的開拓
天空海闊,要討最并行的生活
我喜歡我,讓矢量算出一種結(jié)果
簡(jiǎn)單的指令集,一樣加速的很妥妥
他的名字,叫做
SIMD
Single Instruction Multiple Data
話接上回《窺腦究竟,結(jié)網(wǎng)造芯(三)》我們說(shuō)到,有三種方式,可以在傳統(tǒng)體系結(jié)構(gòu)的基礎(chǔ)上面向神經(jīng)網(wǎng)絡(luò)人工智能硬件進(jìn)行優(yōu)化設(shè)計(jì)。這次,我們先來(lái)提第一種——在簡(jiǎn)單指令集(RISC)中增加指令的方式來(lái)達(dá)到性能的優(yōu)化。我們將著重介紹如何加速卷積核的計(jì)算(忘了(一)和(二)?點(diǎn)這里?。?/p>
這次的故事,要從并行計(jì)算機(jī)體系結(jié)構(gòu)講起。說(shuō)到并行計(jì)算機(jī)體系結(jié)構(gòu),就要掉一個(gè)書袋——
我從上的第一門計(jì)算機(jī)體系結(jié)構(gòu)課,到并行提算計(jì)體系機(jī)構(gòu),到高級(jí)計(jì)算機(jī)體系結(jié)構(gòu)都在用這一本書。不得不感謝作者讓我少買了好多教科書錢。當(dāng)然,牛x書的作者也很牛x,這里就不八卦了。有人愿意把這本書叫做計(jì)算機(jī)體系結(jié)構(gòu)的bible,我不評(píng)論,但是下面我們所講的,好多都出自這本書。
言歸正傳,這個(gè)特立獨(dú)行的故事從這里開先,我們要認(rèn)識(shí)一個(gè)老爺爺(還活著好像),他叫Michael Flynn。老人家生于大蕭條時(shí)代的扭腰城,一不小心提出了一個(gè)分類法,叫做Flynn Taxonomy(1966)。然后計(jì)算機(jī)體系機(jī)構(gòu)就被Flynn taxonomy的五指山給壓幾十年。
Flynn Taxonomy的五指山把計(jì)算機(jī)結(jié)構(gòu)分為兩個(gè)部分:指令與數(shù)據(jù)。在時(shí)間軸上指令與數(shù)據(jù)可以單步執(zhí)行或多次運(yùn)行進(jìn)行分類,即單指令單數(shù)據(jù)(SISD),單指令多數(shù)據(jù)(SIMD),多指令單數(shù)據(jù)(MISD)和多指令多數(shù)據(jù)(MIMD)。
并行,從Pipeline到SIMD
Flynn taxonomy給并行計(jì)算機(jī)體系結(jié)構(gòu)指了兩條明路——指令級(jí)并行和數(shù)據(jù)級(jí)并行。
首先來(lái)看下指令與數(shù)據(jù)的關(guān)系。指令是處理器單步可以實(shí)現(xiàn)的操作的集合。指令集里的每一條指令,都包含兩個(gè)部分:(1)什么操作;(2)對(duì)什么數(shù)據(jù)進(jìn)行操作。專業(yè)地,我們把前者叫做opcode,后者叫做operand(也就是數(shù)據(jù))。當(dāng)然,并不是所有的命令都有數(shù)據(jù)操作。傳統(tǒng)定義的指令集里面,對(duì)應(yīng)的operand不超過(guò)2。比如,加減乘除都是典型的二元操作。數(shù)據(jù)讀寫就是一元的,還有些就是沒有任何數(shù)據(jù)的操作,比如一個(gè)條件判斷(if)發(fā)生了,根據(jù)判斷結(jié)果程序何去何從,只是一個(gè)jump操作,他并不需要任何數(shù)據(jù)輸入。
指令級(jí)并行的第一種、也是最經(jīng)典的辦法叫做時(shí)間上并行,這是所有的體系結(jié)構(gòu)教科書最喜歡教的流水線架構(gòu)(pipeline)。簡(jiǎn)而言之,在發(fā)明流水線以前,處理器里面只有一個(gè)老司機(jī),什么事情都得他來(lái)干,但是下一條指令得等老司機(jī)干完上一個(gè)~但是,流水線就是把一個(gè)老死機(jī)變成了三個(gè)臭皮匠,每個(gè)人干三分之一就給下一個(gè),這樣下一條指令只需在上一條被干完1/3后就可以進(jìn)來(lái)了。雖然老司機(jī)體力好,但趕不上年輕的臭皮匠干的快啊。這樣,流水線可以實(shí)現(xiàn)時(shí)間上的指令集并行,成倍提高實(shí)際指令的處理效率。
經(jīng)典MIPS-5 級(jí)流水線
有一就有二,有時(shí)間當(dāng)然就有空間。所以,第二種辦法是空間上的并行??臻g并行基于一個(gè)觀察——對(duì)數(shù)據(jù)的操作有很多種——加減乘除移位、整數(shù)操作、浮點(diǎn)操作……每一個(gè)模塊的處理(ALU/EXU)是獨(dú)立的,所以,就空間上,一個(gè)浮點(diǎn)加法在處理的時(shí)候,完全可以同時(shí)進(jìn)行一個(gè)整數(shù)移位操作,像老頑童教小龍女的左右互搏分心二用。所以,在計(jì)算機(jī)體系的歷史上,練成“左右互博”術(shù)的處理器包括超標(biāo)量(Superscalar)/超長(zhǎng)指令(Very Long Instruction Word, VLIW)處理器。具體我們先不展開。
相比于流水線/超標(biāo)量復(fù)雜的修煉過(guò)程(黃蓉都練不會(huì)“左右互博”),數(shù)據(jù)級(jí)并行就是簡(jiǎn)單純粹的疊加硬件,打造并行處理的“千手觀音”:
“千手觀音”的學(xué)名叫做SIMD,Single Instruction Multiple Data,單指令多數(shù)據(jù)(流)處理器。其實(shí),說(shuō)白了就是原來(lái)有處理單元(ALU/EXU)現(xiàn)在一個(gè)加法器,現(xiàn)在變成了N個(gè)了。對(duì)應(yīng)神經(jīng)網(wǎng)絡(luò)的計(jì)算,原來(lái)要M次展開的乘累加,現(xiàn)在只要M/N次,對(duì)應(yīng)的時(shí)鐘和時(shí)間都顯著地降低。
簡(jiǎn)單粗暴的并行,不僅提高了讓每個(gè)指令的數(shù)據(jù)吞吐率,還讓本身單一的標(biāo)量處理進(jìn)化成陣列式的“矢量型”處理,于是就有SIMD又有了“矢量處理”指令的稱呼。其實(shí),SIMD并不是到了神經(jīng)網(wǎng)絡(luò)再興起的新玩樣兒,早在MP3的年代,SIMD處理器就廣泛地使用在各類信號(hào)處理芯片中。所以關(guān)于SIMD指令也早有了需要行業(yè)標(biāo)準(zhǔn)。以下,我們就來(lái)看一個(gè)SIMD指令集實(shí)例——
ARM NEON,厲害了word令
在上一編中,我們簡(jiǎn)單提到了史上第一個(gè)攻城掠地的RISC-ARM。為手機(jī)、平板等便攜式的最重要處理器,ARM的SIMD指令也是王者風(fēng)范,從它的名字開始——NEON。
NEON的指令的操作的輸入(operand)是一組128位位寬的寄存器,但這個(gè)寄存器存著的幾個(gè)數(shù),就由碼農(nóng)自己去預(yù)定義了,可以是4個(gè)32位的浮點(diǎn),或者定點(diǎn),或者8個(gè)16位定點(diǎn),或者16個(gè)8位定點(diǎn)……整個(gè)指令集寬泛地定義了輸入、輸出的位寬,供變成者自由支配,考慮到在神經(jīng)網(wǎng)絡(luò)中,前饋網(wǎng)絡(luò)往往只要16位、8位整數(shù)位寬,所以最高效的NEON命令可以一次實(shí)現(xiàn)16個(gè)乘累加計(jì)算(16個(gè)Synapse)。
僅僅是SIMD怎能彰顯NEON的俠者風(fēng)范? NEON還充分應(yīng)用了指令級(jí)并行,采用10級(jí)流水線(4級(jí)decode+6級(jí)運(yùn)算單元),可以簡(jiǎn)單地理解為把卷積計(jì)算的吞吐率由提高了10倍。加起來(lái),相比與傳統(tǒng)的單指令5級(jí)流水,提高至少32倍的效率。再輔以ARM Cortex A7以上的超標(biāo)量核心處理單元,筑起了第一條通用并行計(jì)算的快車道。
當(dāng)神經(jīng)網(wǎng)絡(luò)遇上SIMD,滑起吧!
流水線和SIMD都是在神經(jīng)網(wǎng)絡(luò)還沒羽翼豐滿的時(shí)候就已經(jīng)稱霸江湖的大俠。在神經(jīng)網(wǎng)絡(luò)不可一世的今天,這兩者還是固步自封么?答案顯然是否定的。
當(dāng)通用SIMD處理器遇上神經(jīng)網(wǎng)絡(luò),他們既碰撞出了火花,也開始相互埋怨。我們先說(shuō)埋怨——存儲(chǔ)空間管理。我們知道,在NN中通常每個(gè)卷積核都需要先load系數(shù)與輸入數(shù)據(jù),再算出部分的乘累加結(jié)果,再store回存儲(chǔ)空間。而指令執(zhí)行與存儲(chǔ)空間的通信就是我們上一編講到的——馮諾伊曼瓶頸。對(duì)于神經(jīng)網(wǎng)絡(luò)來(lái)說(shuō),如此多次的存儲(chǔ)讀寫是制約性能的關(guān)鍵。減少數(shù)據(jù)的載入與中間結(jié)果是面向神經(jīng)網(wǎng)絡(luò)的SIMD指令的主要問題。
那火花是什么?
這就給SIMD帶來(lái)了一個(gè)面向神經(jīng)網(wǎng)絡(luò)的新機(jī)遇——部分更新與數(shù)據(jù)滑行(sliding)。我們來(lái)看下面這張動(dòng)圖「原作為MIT Eyeriss項(xiàng)目研究組」。
對(duì)于一個(gè)采用SIMD的卷積核,有一組輸入是固定——系數(shù)矢量,而另一組輸入像一個(gè)FIFO,在起始填滿后,每次注入一個(gè)單元(也排出一個(gè)單元)進(jìn)行乘雷佳,另外上一次累加的結(jié)果在保存在執(zhí)行單元的寄存器內(nèi),只有最終的卷積核結(jié)果會(huì)寫回到存儲(chǔ)器中。
這樣,在神經(jīng)網(wǎng)絡(luò)中,無(wú)論是數(shù)據(jù)導(dǎo)入、還是結(jié)果輸出,起對(duì)存儲(chǔ)空間的訪問都會(huì)大大降低。當(dāng)然,上述示意圖僅僅是一維的。當(dāng)卷積核的維度達(dá)到二三維時(shí),情況會(huì)復(fù)雜很多。這里推薦大家可以去讀讀MIT的Eyeriss,Kaist的MIMD,或者IMEC的2D-SIMD(ENVISION)。這里就不太多展開了。
好了,這次就到這里。所謂“燭臺(tái)簇華照單影”就是那一粒粒自由定義的小數(shù)據(jù),在同一聲SIMD的指令下,排成隊(duì),集成行,成為了一個(gè)孤獨(dú)的矢量運(yùn)算。
特別鳴謝復(fù)旦大學(xué)腦芯片研究中心提供技術(shù)咨詢,歡迎有志青年報(bào)考。
雷峰網(wǎng)原創(chuàng)文章,未經(jīng)授權(quán)禁止轉(zhuǎn)載。詳情見轉(zhuǎn)載須知。