RenderScript 之外的另一個選擇:FilterScript

快速複習,RenderScript 是什麼?

想了解細節可以回顧一下以前的文章。簡單來說,RenderScript(以下簡稱 RS)的作用就如同 OpenCL 一樣,是個可以同時處理計算與繪圖的程式語言。差別在於 RenderScript 是 Android 獨有的,OpenCL 卻與 OS 無相關,根據 PowerVR 的說法,OpenCL 要針對一個新的硬體新增 API 相當不容易,得透過各軟硬體的供應上同意並且投票通過才可以進行。反之,Google 身為純軟體公司的角色就比較中立,目標只有設法減輕應用程式開發者的負擔,所以可以快速地針對各硬體廠商的需求做出反應。

RenderScript 不夠好嗎?

The initial top-down approach has led to some confusion among developers regarding the level of support for CPU/GPU architectures. Key to remember is that all PowerVR devices, based on the SGX or ‘Rogue’ architecture, support both Renderscript and Filterscript. GPU acceleration will be difficult to predict, as it depends on the features used in the script, but also on how busy the GPU is (e.g. with graphics or other compute tasks). By using Filterscript, you will in general have a higher chance of acceleration on GPUs from Imagination or other vendors.

即便設計之初,RenderScript 的目的就是可以同時處理 Computing 與 Rendering,但是在 Android 3.0 宣布正式推出 RenderScript 之初,主要還是著重 CPU,也就是透過 CPU 計算、並且以 CPU 做圖形運算。在後續的版本才逐步地加入其他硬體單元的支援設法加速 RS 應用(如:NEON, SIME FP Unit)。某些硬體單元因為沒有支援 ALU 精準度所以沒辦法被 RenderScript 支援,Google 後來也在 API 的設計上最了讓步,提供了

#pragma rs_fp_relaxed
宣告 Relaxed Precision 允許開發者運用這些硬體單元替 RS 應用加速。

GPU 的需求與日俱增,到了 Android 4.1,RenderScript 終於可以支援 GPU 裝置了,但是因為 RS 要兼顧通用性(當初設計的目的),因此開發者是很難預測一個 RS 應用跑在不同裝置時,到底是使用 CPU 還是 GPU 的運算資源,甚至當 CPU 與 GPU 交互運作時,常常會出現預期之外的行為(如:明明裝置上有 GPU,但不知道什麼原因,最後走的是 CPU Path,讓程式運行速度不如預期)。

即使透過 #pragma 強制宣告可以解決這些問題,但是開發者往往會忽略加上 #pragma,而且對於開 發者而言,程式應該可以 “Write Once, Run Anywhere.",並且可以在不同的硬體上各自跑出最佳的效能,而不是又帶來另外一種 Fragmentation => 不同型號間的 CPU/GPU,CPU/GPU 核心數。

FilterScript 與 RenderScript 不同之處

Filterscript defines constraints on the existing Renderscript APIs that allow the resulting code to run on a wider variety of processors (CPUs, GPUs, and DSPs). To create Filterscript files, create .fs files instead of .rs files, and specify #pragma rs_fp_relaxed to tell the Renderscript runtime your scripts do not require strict IEEE 754-2008 floating point precision. This precision allows flush-to-zero for denorms and round-towards-zero. In addition, your Filterscript scripts must not use 32-bit built-in types and must specify a custom root function by using the__attribute__((kernel)) attribute because Filterscript does not support pointers, which the default signature of the root() function defines.

因為上述的原因,在 Android 4.2 推出了 FilterScript相較於 RenderScript 著重在 CPU 和通用性上,FilterScript 著重的則是 GPU 和高性能

有了 FS 與 RS,開發者可以根據不同的選擇適配語言來開發:

  • 如果是面向大眾的平價機種,那麼就選擇 RS。因為 RS 將市面上主流的 CPU (如:MIPS, x86, ARM)做了抽象化,讓開發者可以不用顧慮可移植性。
  • 如果是旗艦機種,那麼就選擇 FS,盡可能地發揮出 100% 的硬體性能。

目前 Android 官方文件尚無較完整的 FilterScript 介紹,不過根據 Stackoverflow 的這篇討論看來,基本上不論程式語法或是 Runtime 應該都與 RenderScript 相去不大,除了以下:

In general, it requires attribute((kernel)), no pointers, and no unions, and fp_relaxed is implied by the file type.

參考資料:

  1. http://blog.imgtec.com/powervr/compute-apis-renderscript-filterscript-google
  2. http://blog.imgtec.com/powervr/gpu-compute-on-powervr-with-androids-filterscript