在 Android 內部實做中,有許多細節涉及大量的 memcpy() 操作,比方說將一塊使用者定義的繪圖區域傳遞給 SurfaceFlinger 管理的過程,由於得先轉換成 texture,再對應為 Surface,之間至少需要三次 memcpy。由於 BeagleBoard (TI OMAP3) 透過 HDMI 輸出 (max: 1280x1024),居中涉及大量的繪圖操作,意味著 memcpy() 頻繁被呼叫著,對整體效能有顯著的影響,於是筆者花了一些時間分析。
Android 的 libc 實做 -- bionic -- 已包含針對 ARMv5 優化過的 memcpy(),詳情可參考 libc/arch-arm/bionic/memcpy.S,而 GNU Toolchain (glibc) 中,其實也有一份針對 ARMv5 優化過的 memcpy() 實做,也利用到 ARMv5 的 data prefetch 指令。既然我們採用 ARMv7 架構的 BeagleBoard,何不使用其引入的 NEON SIMD 加速指令集呢?以下就是在 BeagleBoard 所作的 benchmark:
數據如下:
- glibc-armv5 : 181884276 B/s
- bionic-armv5 : 225881095 B/s
- armv7 : 269294302 B/s
- .fpu neon
- .text
- .global memcpy_neon
- .func memcpy_neon
- memcpy_neon:
- push {r4-r11}
- mov r3, r0
- 1: subs r2, r2, #128
- pld [r1, #64]
- pld [r1, #256]
- pld [r1, #320]
- ldm r1!, {r4-r11}
- vld1.64 {d0-d3}, [r1,:128]!
- vld1.64 {d4-d7}, [r1,:128]!
- vld1.64 {d16-d19}, [r1,:128]!
- stm r3!, {r4-r11}
- vst1.64 {d0-d3}, [r3,:128]!
- vst1.64 {d4-d7}, [r3,:128]!
- vst1.64 {d16-d19}, [r3,:128]!
- bgt 1b
- pop {r4-r11}
- bx lr
- .endfunc
1 意見:
Jump to comment form | comments rss | trackback uri