Linux, 工作, 生活, 家人

ARM, Linux

如何確認 uclibc 是有 VFP 最佳化的?

這標題隨便下的, 只是一個筆記的 Note.

一般來說使用 arm 的平台很少會去注意是不是有 VFP 支援, 一般 Embedded Linux 內會用到數學函式運算的系統不多. (當然 Android 之後就變多了).

首先看來一個簡單的程式
[C]
int main(void){
double a=2.2,b=1.1,c;

c=a*b;
return 0;
}
[/C]
這時用 arm-linux-gcc 去 compile 這行程式, 預設是 software floating point
我們會看到, 程式會去呼叫 function __aeabi_mul 去運算 dmul.

[BASH]
# arm-linux-gcc -c -g -Wa,-a,-ad 1.c ; arm-linux-objdump -dS 1.o | less
[/BASH]

[TEXT]
c=a*b;
30: e24b002c sub r0, fp, #44 ; 0x2c
34: e8900003 ldm r0, {r0, r1}
38: e24b2024 sub r2, fp, #36 ; 0x24
3c: e892000c ldm r2, {r2, r3}
40: ebfffffe bl 0 <__aeabi_dmul>
44: e1a03000 mov r3, r0
48: e1a04001 mov r4, r1
4c: e50b301c str r3, [fp, #-28]
50: e50b4018 str r4, [fp, #-24]
[/TEXT]

如果是使用 VFP 呢? 只要簡單幾行指令就可以完成原來還要呼叫 eabi_dmul 的事情
[BASH]
# arm-linux-gcc -mfloat-abi=softfp -c -g -Wa,-a,-ad 1.c ; arm-linux-objdump -dS 1.o | less
[/BASH]
可以得到
[TEXT]
c=a*b;
30: ed1b6b0b vldr d6, [fp, #-44]
34: ed1b7b09 vldr d7, [fp, #-36]
38: ee267b07 fmuld d7, d6, d7
3c: ed0b7b07 vstr d7, [fp, #-28]
[/TEXT]

而 __eabi_dmul 藏在那邊呢? 答案就在 gcc 內
在 gcc source code , gcc/config/arm/arm.c: 內有這一行 define
set_optab_libfunc (smul_optab, DFmode, “__aeabi_dmul”);
而 gcc/config/arm/ieee754-df.S 內記錄著 aeabi_dmul 的實際 software code.
看起來落落長, 難怪效能差很多 :p

那 uclibc binary 有沒有支援 vfp 怎麼檢查呢 ?
我先暫時是去 dump libm.so 的內容, 如果有使用到 vldr, fmuld 之類的指令, 表示確實有用到 VFP 的指令.
[BASH]
# arm-linux-objdump -dS libm-0.9.31.so
[/BASH]
*註: 看起來 uclibc 會有自己的數學指令(不確定)

uclibc 要如何支援, 如果是用 buildroot, 在 uclibc 的 configure file 加上一行
[TEXT]
UCLIBC_EXTRA_CFLAGS=”-mfloat-abi=softfp”
[/TEXT]

編完 uclibc 之後, 我們可以用 objdump 看 libm.so 的 Assembly code
[BASH]
# arm-linux-objdump -D libm-0.9.31.so | less
[/BASH]

有 v 開頭的指令很多都是 vfp 的指令
[TEXT]
00007dd0 :
7dd0: e1a03001 mov r3, r1
7dd4: e3c32102 bic r2, r3, #-2147483648 ; 0x80000000
7dd8: e59f30a4 ldr r3, [pc, #164] ; 7e84

7ddc: e52de004 push {lr} ; (str lr, [sp, #-4]!)
7de0: e1520003 cmp r2, r3
7de4: e24dd01c sub sp, sp, #28 ; 0x1c
7de8: ec410b17 vmov d7, r0, r1
7dec: d3a02000 movle r2, #0 ; 0x0
7df0: d3a03000 movle r3, #0 ; 0x0
7df4: d3a0c000 movle ip, #0 ; 0x0
7df8: da000010 ble 7e40

7dfc: e59f3084 ldr r3, [pc, #132] ; 7e88

7e00: e1520003 cmp r2, r3
7e04: ce376b47 fsubdgt d6, d7, d7
7e08: cc510b16 vmovgt r0, r1, d6
[/TEXT]

最後測試 Library 的速度, 以下是測試 Code.
[C]
cat 1.c
#include
#include

int main(void){

double result,result2; int i,j,count=0;

for(j=0;j<10000;j++){ for(i=0;i<180;i++){ result = sin(i); result2 = sin(0-i); if(result == -result2){ count++; } } }

printf(” count:%d\n”, count);

return 0; } [/C] 無 VFP Library Support 的數據. [TEXT] count:1800000 real 0m 15.64s user 0m 15.64s sys 0m 0.00s [/TEXT] 有 VFP Library Support 的數據 [TEXT] count:1800000 real 0m 2.42s user 0m 2.42s sys 0m 0.00s [/TEXT] 差了 6.46 倍.

發佈留言