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