arm浮点运算
首先總結(jié)一下計(jì)算機(jī)中的浮點(diǎn)數(shù)的存儲(chǔ)。
浮點(diǎn)數(shù)的標(biāo)準(zhǔn)是IEEE-754,規(guī)定了浮點(diǎn)數(shù)的存儲(chǔ)都是通過科學(xué)計(jì)算法來存儲(chǔ)的,n2-e的表示。
浮點(diǎn)數(shù)首先分為,定浮點(diǎn)(fixed-point)和浮點(diǎn)(float-point),定浮點(diǎn)就是說e的值是不變的。
目前浮點(diǎn)的計(jì)算都是將浮點(diǎn)轉(zhuǎn)換為定浮點(diǎn)來計(jì)算,由此衍生出,單精度浮點(diǎn)和雙精度浮點(diǎn)。
浮點(diǎn)數(shù)的存儲(chǔ),前半部分表示exponent(可以是負(fù)數(shù),使用補(bǔ)碼表示),后半部分表示fraction(規(guī)定fraction必須是1.x的格式)。
單精度的儲(chǔ)存位寬是32bit,e占8bit,最大表示-127----128,fraction占23bit。
雙精度的存儲(chǔ)位寬是64bit,e占11bit,最大表示-1023---1024,fraction占52bit。
e的表示采用以偏置形式表示的有符號(hào)整數(shù),單精度的e,計(jì)算應(yīng)該表示為e+127從而消除負(fù)數(shù)。雙精度的e,計(jì)算應(yīng)該表示為e+1023。
fraction采用小數(shù)的表示方法,小數(shù)點(diǎn)之前除2得余數(shù)為二進(jìn)制表示。小數(shù)點(diǎn)之后乘2得整數(shù)部分未二進(jìn)制表示:
176.0625表示為單精度浮點(diǎn)數(shù),
176/2 得 88,余0
88/2 得 44,余0
44/2 得 22,余0
22/2 得 11,余0
11/2 得 5, 余1
5/2 得2, 余1
2/2 得1, 余0
1/2 得0, 余1 商為零結(jié)束。
小數(shù)點(diǎn)之前的表示為1011_0000
0.0625*2 得0.125, 整數(shù)部分為0
0.125*2 得0.25, 整數(shù)部分為0
0.25*2 得0.5, 整數(shù)部分為0
0.5*2 得1, 整數(shù)部分為1,小數(shù)部分為0,結(jié)束。
小數(shù)點(diǎn)之后的表示為0001。(小數(shù)部分不一定可以被準(zhǔn)備的表示出來,小數(shù)以5結(jié)尾為必要條件)
176.0625表示為單精度浮點(diǎn)數(shù),1011_0000.0001
比如1.01 X 2-3,其中exponent表示-3+127=124(0111_1100),.01表示fraction。
單精度和雙精度的,精度對(duì)比:
浮點(diǎn)數(shù)的規(guī)則化(normalized):
fraction必須是|1.x|的格式;
非規(guī)則化的數(shù):
正零:所有bit都為0;
負(fù)零:除了符號(hào)位,都為0;
無窮大:exponent的所有bit都為1;fraction的所有值都為0;
負(fù)無窮大:exponent的所有bit都為1;fraction的所有值都為0,符號(hào)位為1;
非法數(shù)值:exponent的所有bit都為1;fraction的值不全為0;NaN(Not a Number)
浮點(diǎn)數(shù)的計(jì)算:
1)判斷是否有操作數(shù)為0;
2)對(duì)階:小階向大階對(duì)齊,階小的那個(gè)數(shù)(看正負(fù)),exponent加n,fraction右移n位。
3)加減運(yùn)算,fraction做加減運(yùn)算,exponent不變。
4)結(jié)果規(guī)格化。(這時(shí)會(huì)有舍入處理,IEEE754規(guī)定了幾種舍入)
判斷溢出,浮點(diǎn)只有exponent的上溢,(正數(shù)相加不為負(fù),負(fù)數(shù)相加不為正);
加減:
乘法:
除法:
平方根:
Basic op:
arm的vfp實(shí)現(xiàn)有vfpv3和vfpv4兩種,vfpv4相比較與vfpv3主要增加了half-precision extension和乘加的指令。
arm的vfp可以實(shí)現(xiàn)為32個(gè)或16個(gè)double-word register,分別以vfpv3-D32和vfpv3-D16來表示。 但是neon和vfp同時(shí)實(shí)現(xiàn)時(shí),vfp只可以實(shí)現(xiàn)為vfp-D32。
vfp的主要控制寄存器:
1) FPSCR(Status Control reg),保存FP運(yùn)算之后的flags,rounding options,enable exception trapping。
VCMP d0,d1
VMRS APSR_nzcv, FPSCR,將SCR中的flags加載到apsr中,才能進(jìn)行比較指令的跳轉(zhuǎn)
BNE label
2) FPEXC(Exception reg),處理各種exception,包括FP計(jì)算過程中的overflow,underflow,inexact(需要進(jìn)行rounding),invalid(NaN),Division by zero等,
硬件FP單元的使用,需要在編譯器(gcc)中進(jìn)行選項(xiàng)標(biāo)注:
1) -mfpu=vfp/neon/vfpv3/vfpv4/vfpv4-d16等。指明硬件FP單元;
2) -mfloat-abi = softfp、hardfp,指明abi接口,進(jìn)行正常的context switching過程中的寄存器進(jìn)棧出棧。
如果是arm compiler,需要的選項(xiàng),--fpu=vfpv3/vfpv3_d14等,--apcs=/hardfp或者/softfp等。
arm的SIMD指令的發(fā)展:
SIMD,一般應(yīng)用在數(shù)據(jù)量較大的場合,使用一條指令,加載多個(gè)同樣type和size的數(shù)據(jù),并對(duì)數(shù)據(jù)進(jìn)行并行處理;
例如,2個(gè)32bit的數(shù)據(jù)加法,被替換為,4個(gè)8bit的數(shù)據(jù)加法。
armv6,提出一些SIMD的指令,將多個(gè)16bit,8bit的數(shù)據(jù)加載到32bit寄存器中,但是并沒有單獨(dú)的執(zhí)行單元,
也沒有單獨(dú)的流水線。指令名字就是在之后加16或8的后綴。使用32bitSIMD。
armv7,引入了advanced SIMD,定義了自己的向量寄存器,32*64bit register file,自己的流水線執(zhí)行單元。這些SIMD的擴(kuò)展被稱為NEON。
向量寄存器,是一組64bit的雙字,或128bit的四字,使用64bit或者128bit的SIMD。
NEON指令可以實(shí)現(xiàn):
1) 存儲(chǔ)空間訪問;
2) 在NEON和general寄存器之間的數(shù)據(jù)copy;
3) 數(shù)據(jù)類型轉(zhuǎn)換;
4) 數(shù)據(jù)計(jì)算;支持8bit(vido image的pixel data),16bit(audio codecs data),32bit,64bit的符號(hào)數(shù)整型,32bit/16bit的單精度浮點(diǎn),
neon可以和vfp同時(shí)使用,但由于寄存器是公用的,vfp必須實(shí)現(xiàn)為D32 form,
V7中NEON與VFP的計(jì)算對(duì)比:
1) NEON是SIMD指令,主要處理vector數(shù)據(jù),并行度也高(最多是4),vfp是scalar指令,SISD的形式處理FP。
2) VFP支持全I(xiàn)EEE754的標(biāo)準(zhǔn),NEON只支持單精度浮點(diǎn),不支持square root或者divide。
NEON指令:
VADD.I16 q0, q1, q2,表示使用8個(gè)16bit的并行加,
VMULL.S16, Q0, D2, D3,表示使用4個(gè)16bit的并行乘,
NEON在使用gcc編譯器時(shí)的選項(xiàng):
1) 編譯匯編(指明abi接口和fpu接口),arm-none-linux-gnueabi-as -mfpu=neon asm.s
2) 關(guān)聯(lián)函數(shù)intrinsics,#include <arm_neon.h>
uint32x4_t double_elements(uint32x4_t input)
{ return(vaddq_u32(input, input));
}
arm-none-linux-gnueabi-gcc -mfpu=neon intrinsic.c
3) 優(yōu)先矢量化(盡可能的使用SIMD來提高性能),arm-none-linux-gnueabi-gcc -mfpu=neon -ftree-vectorize -c vectorized.c
4) 使用優(yōu)化庫,OpenMAX,需要下載安裝,程序中加入頭文件,#include <omxSP.h>
VFP在使用時(shí),與NEON的編程類似,寄存器一部分是共享的。
在armv8中,有分別針對(duì)aarch32(等同于v7)和aarch64的NEON指令;v8中的aarch64中使用32*128bit的register file;
v8中FP和NEON均作為一個(gè)標(biāo)準(zhǔn)部件,繼承在core內(nèi)部。
aarch64中的neon完全支持IEEE754標(biāo)準(zhǔn)的所有FP操作,雙精度,NaN handling,rounding等。
在v8中,neon指令和fp指令與a64的指令相同,根據(jù)之后的操作數(shù)寄存器來區(qū)分(v7中neon,fp指令前加v):
總結(jié)
- 上一篇: rancher学习:rancher组成
- 下一篇: 富文本(wangEditor框架)的使用