arm浮點運算

首先總結一下計算機中的浮點數的存儲linux

浮點數的標準是IEEE-754,規定了浮點數的存儲都是經過科學計算法來存儲的,n2-e的表示。算法

  浮點數首先分爲,定浮點(fixed-point)和浮點(float-point),定浮點就是說e的值是不變的。編程

  目前浮點的計算都是將浮點轉換爲定浮點來計算,由此衍生出,單精度浮點和雙精度浮點app

 

浮點數的存儲,前半部分表示exponent(能夠是負數,使用補碼錶示),後半部分表示fraction(規定fraction必須是1.x的格式)。ide

單精度的儲存位寬是32bit,e佔8bit,最大表示-127----128,fraction佔23bit。函數

雙精度的存儲位寬是64bit,e佔11bit,最大表示-1023---1024,fraction佔52bit。性能

e的表示採用以偏置形式表示的有符號整數,單精度的e,計算應該表示爲e+127從而消除負數。雙精度的e,計算應該表示爲e+1023。優化

fraction採用小數的表示方法,小數點以前除2得餘數爲二進制表示。小數點以後乘2得整數部分未二進制表示:ui

  176.0625表示爲單精度浮點數,scala

  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   商爲零結束。

  小數點以前的表示爲1011_0000

  0.0625*2    得0.125, 整數部分爲0

  0.125*2      得0.25,   整數部分爲0

  0.25*2        得0.5,     整數部分爲0

  0.5*2          得1,   整數部分爲1,小數部分爲0,結束。

  小數點以後的表示爲0001。(小數部分不必定能夠被準備的表示出來,小數以5結尾爲必要條件)

  176.0625表示爲單精度浮點數,1011_0000.0001

好比1.01 X 2-3,其中exponent表示-3+127=124(0111_1100),.01表示fraction。

  

單精度和雙精度的,精度對比:

  

浮點數的規則化(normalized)

  fraction必須是|1.x|的格式;

非規則化的數:

  正零:全部bit都爲0;

  負零:除了符號位,都爲0;

  無窮大:exponent的全部bit都爲1;fraction的全部值都爲0;

  負無窮大:exponent的全部bit都爲1;fraction的全部值都爲0,符號位爲1;

  非法數值:exponent的全部bit都爲1;fraction的值不全爲0;NaN(Not a Number)

 

浮點數的計算:

  1)判斷是否有操做數爲0;

  2)對階:小階向大階對齊,階小的那個數(看正負),exponent加n,fraction右移n位。

  3)加減運算,fraction作加減運算,exponent不變。

  4)結果規格化。(這時會有舍入處理,IEEE754規定了幾種舍入)

    判斷溢出,浮點只有exponent的上溢,(正數相加不爲負,負數相加不爲正);

加減:

  

乘法:

  

除法:

   

平方根:

  

Basic op:

  

 

  

 

arm的vfp實現有vfpv3和vfpv4兩種vfpv4相比較與vfpv3主要增長了half-precision extension和乘加的指令

arm的vfp能夠實現爲32個或16個double-word register,分別以vfpv3-D32和vfpv3-D16來表示。 可是neon和vfp同時實現時,vfp只能夠實現爲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指令的發展

SIMD,通常應用在數據量較大的場合,使用一條指令,加載多個一樣type和size的數據,並對數據進行並行處理

  例如,2個32bit的數據加法,被替換爲,4個8bit的數據加法。

armv6,提出一些SIMD的指令,將多個16bit,8bit的數據加載到32bit寄存器中,可是並無單獨的執行單元

  也沒有單獨的流水線。指令名字就是在以後加16或8的後綴。使用32bitSIMD。

armv7,引入了advanced SIMD,定義了本身的向量寄存器,32*64bit register file,本身的流水線執行單元。這些SIMD的擴展被稱爲NEON

  向量寄存器,是一組64bit的雙字,或128bit的四字,使用64bit或者128bit的SIMD。

  NEON指令能夠實現:

  1) 存儲空間訪問;

  2) 在NEON和general寄存器之間的數據copy;

  3) 數據類型轉換;

  4) 數據計算;支持8bit(vido image的pixel data),16bit(audio codecs data),32bit,64bit的符號數整型,32bit/16bit的單精度浮點,

neon能夠和vfp同時使用,但因爲寄存器是公用的,vfp必須實現爲D32 form,

V7中NEON與VFP的計算對比

  1) NEON是SIMD指令,主要處理vector數據,並行度也高(最可能是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) 關聯函數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) 優先矢量化(儘量的使用SIMD來提升性能),arm-none-linux-gnueabi-gcc  -mfpu=neon  -ftree-vectorize  -c vectorized.c

   4) 使用優化庫,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的指令相同,根據以後的操做數寄存器來區分(v7中neon,fp指令前加v):

  

相關文章
相關標籤/搜索