日別アーカイブ: 2012年2月15日

Android 4.0 MIPS で RenderScript, ainol Novo 7 Paladin の浮動小数点演算速度

Novo 7 Paladin は MIPS CPU で Android 4.0 を搭載した端末です。
RenderScript を試してみました。

前回の記事で触れたように、mips 対応版 NDK を入れると対応
アーキテクチャが一気に 6種類に増えます。
さらに armeabi-v7a や mips-r2 の NDK では、ハードウエアの性能を
引き出すために CPU のオプション機能を利用することができます。
ただし搭載していないハードもあるため事前に CPU Features を
チェックしなければなりません。
下記は NDK の cpu-features が返す値です。

armeabi-v7a:
 ANDROID_CPU_ARM_FEATURE_ARMv7
 ANDROID_CPU_ARM_FEATURE_VFPv3
 ANDROID_CPU_ARM_FEATURE_NEON

mips-r2:
 ANDROID_CPU_MIPS_FEATURE_R2
 ANDROID_CPU_MIPS_FEATURE_DSP
 ANDROID_CPU_MIPS_FEATURE_DSP_R2

種類が増えてくると個別最適化は困難となりますし、ビルドや
テストの手間もかかります。
こんな場合 CPU 非依存で Native 相当の実力を持つ RenderScript は
検討する価値がありそうです。

Android 4.0 対応、RenderScript のサンプル

上の記事に掲載したサンプルは MIPS の Paladin でも動作しました。
ただし一部修正が必要でした。
Android 3.x (API 11~13) をターゲットにビルドした RenderScript の
アプリケーションは実行時に下記のようなエラーが出ます。

Could not parse bitcode file
Failed to translate bitcode from version: 11

RenderScript の byte code (bitcode) は Android 3.x (API 11~13)
と Android 4.0 以上 (API 14 以降) で互換性が無いようです。
そのため API Level 14 以上を target にして再コンパイルする
必要があります。

(1) SdkVersion を 14 以上にする

AndroidManifest.xml の SdkVersion を 11 から 14 に修正します。

    

 ↓

    

もし同じフォルダに project.properties ファイルが作られているなら
target=android-15 (または 14) に書き換えます。

(2) rsForEach() を API 14 以降の書式に変更

上のページで紹介したプログラムでは必要ありませんが、Android
SDK 付属の RenderScript サンプルを走らせる場合は必要です。
API 14 以降は rsForEach() の引数が書式が変更されているので、
rsForEach() でコンパイルエラーが出たら引数最後の 0 を削除します。

(3) bc ファイルを作りなおす

bc ファイルを作りなおすためにプロジェクトを一旦 Clean してから
ビルドし直します。
Eclipse の場合はプロジェクトを選択して Menu Project → Clean…

これで Paladin (MIPS + Android 4.0) 上で RenderScript の
プログラムが動くようになります。
描画はそこそこですが CL 系は遅いです。
CPU が Single core であることに加え、浮動小数点演算もあまり
速くないようです。

●実行速度比較(1)

まずは Linpack for Android v1.2.8 で比較してみました

Single   Multi
MFLOPS  MFLOPS   OS   CPU
----------------------------------------------------------------------
18.091  --       2.3  Cortex-A8    1.0GHz S5PC110    Galaxy S SC-02B
18.592  --       4.0  MIPS XBurst  1.0GHz JZ4770     Novo7 Paladin
35.628  --       2.2  Scorpion     1.0GHz QSD8250    Desire X06HT
30.33   57.233   3.1  Cortex-A9 x2 1.0GHz Tegra2     Optimus Pad L-06C
46.164  74.664   2.3  Scorpion  x2 1.2GHz MSM8660    EVO 3D ISW12HT
57.342  92.981   2.3  Cortex-A9 x2 1.2GHz Exynos4210 Galaxy S2 SC-02C
47.071 140.908   3.2  Cortex-A9 x4 1.3GHz Tegra3     EeePad TF201

 * MFLOS の数値が大きい方が速い。
 * Single = Single-Thread
 * Multi = Multi-Thread

Multi Thread はタイミングによるばらつきが大きいため何度か
実行し最速の数値を取っています。あまり正確でないかもしれませんし、
単精度ではまた違った結果になると思います。
取り敢えず Paladin の fpu は激遅の Cortex-A8 VFP に近い速度
ということがわかりました。

●実行速度比較(2)

RenderScript, Java, NDK C, NDK asm の演算比較。
4×4 Matrix * Vector の 50万回。(1)~(13) すべて同じ演算。

                   Paladin     GS   Desire  Tegra2   GS2     GN   Tegra3
                    XBurst     A8  Scorpion  A9x2    A9x2   A9x2   A9x4
                    1.0GHz  1.0GHz  1.0GHz  1.0GHz  1.2GHz 1.2GHz 1.3GHz
------------------------------------------------------------------------
(1) RenderScript A     290      --     --      52      --     29     57
(2) RenderScript B     314      --     --      69      --     44     62
(3) RenderScript C     310      --     --      51      --     31     37
(4) Java Inline        482     698    418     244     179    174    167
(5) Java Matrix      11763    1012   1906    1232    1127   4785    840
(6) NDK (C func)       158     166     60      79      39     39     43
(7) NDK C inline1      267     288     49      66      43     33     41
(8) NDK C inline2      243     289     54      65      46     32     41
(9) NDK asm VFP         --     139     35      46      22     19     35
(10)NDK asm VFP MT2     --     139     37      26      14     15     48
(11)NDK C NEON Intrin   --      26     33      --      26     21     34
(12)NDK asm NEON        --      20     23      --      38     18     32
(13)NDK asm NEON MT2    --      22     29      --      26     17     17

実行時間(msec) 数値が小さいほうが速い。
  * GS=Galaxy S SC-02B,  GS2=Galaxy S2 SC-02C,  GN=Galaxy Nexus SC-04D
  * Tegra2= Optimus Pad L-06C, Tegra3= EeePad TF201
  * A8= Cortex-A8,  A9= Cortex-A9
  * Intrin= Intrinsic (Builtin Function)
  * MT2= Multi thread x2

速いデバイスほど実行時間が短く誤差が出ます。
また演算命令が高速になるほどメモリアクセス速度の影響が増えます。
マルチスレッド実行の場合スレッドの起動や同期によるばらつきが大きく
あまり正確ではありません。

RenderScript の演算では Paladin は A9 dual と 5~10倍くらいの
差が生じていることがわかります。

Paladin の fpu 自体は Cortex-A8 VFP より若干高速です。
ただし、Cortex-A8 も NEON を使うと数倍高速であり、A9 の速度に
ほとんど追い付いています。
Scorpion/A9 になると VFP/NEON 共に安定して速度が出ています。

注意点としてはJava の実行時間には GC が含まれている可能性があります。
また最高でも 2 Thread しか使っていないので Tegra3 は最速ケースでは
ありません。

関連エントリ
Android 4.0 ainol Novo 7 Paladin、MIPS CPU の NDK と Vivante GPU
Android 4.0 対応、RenderScript のサンプル
Android 3.x RenderScript (1)
Snapdragon の本当の浮動小数点演算能力
ARM Cortex-A8 の NEON と浮動小数演算最適化