D3D Shader/OpenGL」カテゴリーアーカイブ

ARM CPU の VFP Benchmark アプリ 浮動小数点演算速度の計測

今まで ARM CPU の浮動小数点演算速度について調べてきましたが、
その計測プログラムをアプリにしてみました。

VFP Benchmark (Android)

今までの測定結果のまとめは下記の通り。

ARM CPU core 毎の浮動小数点演算速度の比較 (VFP/NEON)

VFP Benchmark アプリの表示結果は上記の表と互換性があります。
さらに FLOPS 表示、倍精度浮動小数点演算の計測、マルチスレッド実行に
対応しました。
下記は幾つかの端末の結果(一部)です。

MSN8974 Krait 400 2.2GHz x4 quad
---------------------------------------
SingleT SP max : 16.619 GFLOPS
MultiT  SP max : 67.185 GFLOPS (理論値: 70.4 GFLOPS)
                               = 2(mad) x 4(simd) x 4(core) x 2.2(clock)


Tegra4 Cortex-A15 1.8GHz x4 quad
---------------------------------------
SingleT SP max: 13.371 GFLOPS
MultiT  SP max: 51.345 GFLOPS  (理論値: 57.6 GFLOPS)
                        = 2(mad) x 2(simd) x 2(unit) x 4(core) x 1.8(clock)


APQ8064 Krait 1.5GHz x4 quad
---------------------------------------
SingleT SP max: 11.947 GFLOPS
MultiT  SP max: 47.808 GFLOPS  (理論値: 48.0 GFLOPS)
                               = 2(mad) x 4(simd) x 4(core) x 1.5(clock)

Exynos5D Cortex-A15 1.7GHz x2 dual
---------------------------------------
SingleT SP max: 13.483 GFLOPS
MultiT  SP max: 26.724 GFLOPS  (理論値: 27.2 GFLOPS)
                        = 2(mad) x 2(simd) x 2(unit) x 2(core) x 1.7(clock)


Tegra3 Cortex-A9 1.2GHz x4 quad (TB1.3GHz)
---------------------------------------
SingleT SP max:  4.783 GFLOPS  (理論値:  5.2 GFLOPS
MultiT  SP max: 18.905 GFLOPS  (理論値: 19.2 GFLOPS)
                               = 2(mad) x 2(simd) x 4(core) x 1.2(clock)

K3V2 Cortex-A9 1.2GHz x4 quad
---------------------------------------
SingleT SP max:  4.694 GFLOPS
MultiT  SP max: 18.662 GFLOPS  (理論値: 19.2 GFLOPS)
                               = 2(mad) x 2(simd) x 4(core) x 1.2(clock)


MSN8260 Scorpion 1.2GHz x2 dual
---------------------------------------
SingleT SP max:  8.898 GFLOPS
MultiT  SP max: 16.560 GFLOPS  (理論値: 19.2 GFLOPS)
                               = 2(mad) x 4(simd) x 2(core) x 1.2(clock)


QSD8250 Scorpion 1.0GHz x1
---------------------------------------
SingleT SP max:  7.098 GFLOPS  (理論値:  8.0 GFLOPS)
                               = 2(mad) x 4(simd) x 1.0(clock)

Tegra 2 Cortex-A9 1.0GHz x2 dual
---------------------------------------
SingleT SP max:  1.973 GFLOPS
MultiT  SP max:  3.913 GFLOPS  (理論値:  4.0 GFLOPS)
                               = 2(mad) x 2(core) x 1.0(clock)

比較的理論値に近い数値が出ています。
各 CPU の理論値は下記にまとめました。

CPU FLOPS

この出力結果はあくまでピーク値による比較なので、
実際のアプリケーションの実行速度とは異なります。

例えばスカラ VFP 演算で n8 と n1 の結果を比べると、
Cortex-A9 では命令の並び順によって 5倍も速度が落ちるケースがあります。
同じ条件でも Krait / Cortex-A15 はほとんど速度が落ちていないので、
パイプラインの実行効率が向上していることがわかります。

よって実際のアプリケーションでは、Cortex-A9 と Krait/Cortex-A15 では
ピーク値よりもさらに差が開くことが予想されます。

multi-thread は同じテストを CPU core の数だけ走らせています。
Tegra 3 のように single thread 時に動作クロックが上がるものがあるので、
single-thread の値を core 数倍しても正しい値にならないためです。

アプリの出力結果を見ると、Cortex-A15 は VFP のスカラ演算よりも
NEON の 64bit (float x2) の方が 2倍速く実行できることがわかります。

// Exynos 5 Dual Cortex-A15 1.7GHz dual (Nexus 10)

* VFP/NEON (single fp)         sec    MFLOPS    最大
----------------------------------------------------
VFP fmuls     (32bit x1) n8 :  2.675  1495.4  1555.9
VFP fadds     (32bit x1) n8 :  2.392  1672.1  1672.1
VFP fmacs     (32bit x1) n8 :  3.171  2523.2  2523.2
VFP vfma.f32  (32bit x1) n8 :  2.985  2679.9  2679.9
NEON vmul.f32 (32bit x2) n8 :  1.187  6740.5  6740.5  **
NEON vadd.f32 (32bit x2) n8 :  1.187  6740.7  6740.7  **
NEON vmla.f32 (32bit x2) n8 :  1.187 13480.8 13480.8  **
NEON vfma.f32 (32bit x2) n8 :  1.187 13480.3 13480.3  **
NEON vmul.f32 (32bit x4) n8 :  2.373  6741.8  6741.8
NEON vadd.f32 (32bit x4) n8 :  2.374  6740.7  6740.7
NEON vmla.f32 (32bit x4) n8 :  2.373 13482.7 13482.7
NEON vfma.f32 (32bit x4) n8 :  2.373 13482.3 13482.3

以前予想したようにおそらく NEON の演算 unit は 64bit の 2 pipe ですが、
VFP は 1命令しか実行できない可能性があります。
Cortex-A8 で行ったように、VFP 命令を NEON 演算に置換する
Cortex-A15 最適化ができるかもしれません。

関連エントリ
iPhone 5s A7 CPU の浮動小数点演算速度 (2) (arm64/AArch64/64bit)
iPhone 5s A7 CPU の浮動小数点演算速度 (32bit)
Nexus 10 CPU Cortex-A15 の速度
Nexus 10 CPU Cortex-A15 の浮動小数点演算速度
Qualcomm APQ8064 GPU Adreno 320 の速度
Qualcomm APQ8064 Krait/A6 swift の浮動小数点演算能力
iPad 4/iPad mini A6X/A5 の CPU/GPU 速度
iPhone 5 / A6 の CPU 速度 その 3
ARM Cortex-A8 の NEON と浮動小数演算最適化
benchmark 関連

OpenGL ES 2.0/3.0 Mobile GPU の Shadow Map の違い

・Android Adreno 320 OpenGL ES 3.0 (Nexus 7 2013)
adreno320_nexus7_es3.png

・Android Adreno 320 OpenGL ES 2.0 (HTC J butterfly HTL21 )
adreno320_es2.png

・Android Mali-T604 OpenGL ES 3.0 (Nexus 10 2012)
malit604_nexus10_es3.pngmalit604_nexus10_es3_b.png

・Android Tegra 4 ULP GeForce(72) OpenGL ES 2.0 (Tegra Note 7)
tegra4_note_es2.png

・Android Tegra 3 ULP GeForce(12) OpenGL ES 2.0 (Nexus 7 2012)
tegra3_nexus7_es2_colorbuffer.png

・iOS7 PowerVR SGX543MP3 OpenGL ES 2.0 (iPhone 5)
pvr543mp3_iphone5_es2.png

・iOS7 PowerVR G6430 OpenGL ES 3.0 (iPhone 5s)
pvrg6340_iphone5s_es3.png

・RK3066 Mali-400MP4 OpenGL ES 2.0 (MOMO7)
mali400mp4_es2.png

・Vivante GC4000 OpenGL ES 2.0 (dtab 01)
vivante_gc4000_es2.png

OpenGL ES 2.0 デバイスの大半は GL_OES_depth_texture だけに対応しており
フィルタはかかりません。
depth_texture が無い Tegra2/3 は ColorBuffer で代用しています。

Tegra 4 は OpenGL ES 2.0 ですが Extension で GL_EXT_shadow_samplers に
対応しておりハードウエアで sampling できるようになっています。

同じように iOS の PowerVR Series5XT も OpenGL ES 2.0 ながら早くから
GL_EXT_shadow_samplers に対応していました。
iOS5/6 の当初は PCF もなく見た目が全く変わらなかったのですが、
iOS7 ではいつの間にかフィルタがかかるようになっていました。

なお同じ PowerVR Series5XT の GPU でも Android では残念ながら
shadow_samplers が使えない場合が多いです。

OpenGL ES 3.0 以降は PC 同様そのまま shadow samplers が使えます。
ただし結果は GPU やドライバによってかなり差があるようで、
Adreno 320 や PowerVR G6430 が 4 tap PCF のみ。
逆に Mali-T604 のフィルタは他より質が高くなっています。

                        OS  OpenGL depth-tex sh-sample PCF Linear
-----------------------------------------------------------------
APQ8064 Adreno 320      A44 ES 3.0     ◎       ◎      ◎   --
APQ8064 Adreno 320      A41 ES 2.0     ◎       --      --   --
Exynos5 Dual Mali-T604  A44 ES 3.0     ◎       ◎      ◎   ◎
Tegra 4 ULP GeForce(72) A43 ES 2.0     ◎       ◎      ◎   ◎
Tegra 3 ULP GeForce(12) A44 ES 2.0     --       --      --   --
A6 PowerVR SGX543MP3    i70 ES 2.0     ◎       ◎      ◎   ◎
A7 PowerVR G6430        i70 ES 3.0     ◎       ◎      ◎   --
K3V2 Vivante GC4000     A41 ES 2.0     ◎       --      --   --
RK3066 Mali-400MP4      A41 ES 2.0     ◎       --      --   --
OMAP4430 PowerVR SGX540 A42 ES 2.0     ◎       --      --   --

Tegra 2 → Tegra 3 は core 数(速度) が違うだけで機能は全く同一でした。
対して Tegra 4 の GPU は、Tegra2/3 と比べると大幅に拡張されています。
機能面で見ればほぼ別 GPU といえるほど差があるのですが、
OpenGL ES 3.0 未対応など先行する他 GPU より見劣りする部分もあります。

DX9 世代の G70 ベースの限界なのか、それとも単に Tegra2/3 で
削っていた能力を元に戻しただけなのかもしれません。

一般的に NVIDIA に期待するイメージは強力な GPU でしょう。
ですがこれまでの Tegra は真逆で CPU に偏重した作りでした。
次の Tegra K1 以降はようやく NVIDIA らしい GPU になりそうです。

関連エントリ
OpenGL ES 2.0 Adreno 330, Tegra 4 の GPU 速度

OpenGL ES 2.0 Adreno 330, Tegra 4 の GPU 速度

ベンチマークの結果を更新しました。

Mobile GPU bench mark

Android 4.1 以降かつ対応しているデバイスでは SwapInterval を 0 に
変更したので 60fps 以上出ています。(関連)

GPU            SoC   CPU clock OS    Screen     fps       pix/sec
---------------------------------------------------------------------
Adreno 330     MSM8974 2.2GHz  A4.2  1920x1200  71.98fps   165.8M
Adreno 320(64) APQ8064 1.5GHz  A4.4  1920x1104  40.97fps    86.8M
Mali-T604     Exynos5D 1.7GHz  A4.4  2560x1504  20.73fps    79.8M
ULP GeForce(72) Tegra4 1.8GHz  A4.3   1126x800  44.58fps    43.4M
ULP GeForce(12) Tegra3 1.2GHz  A4.4   1280x752  15.70fps    15.0M (*1)

*1: Shadow Map 無し, 16bit depth

Adreno 330 は予想以上に速く、Adreno 320 比でもおよそ 2倍の速度が出ています。
ついに一番負荷が高い設定でも Full HD (1920×1200) で 60fps を超えるように
なってしまいました。
2010 年の GPU では 800×480 でもわずか 3fps でした。

対する Tegra 4 はあまり速度が伸びていません。
負荷を下げても速度が上がらないので、SwapInterval 設定が効いていないか
何かしら問題が発生している可能性があります。

その代わり Tegra 3 で省かれていたさまざまな extension をサポートしており
描画結果が他の GPU とほぼ一致するようになりました。

特に GL_EXT_shadow_samplers は単なる Hardware ShadowMap ではなく
PCF にきちんと Bi-linear Filter もかかります。
GL_EXT_shadow_samplers は OpenGL ES 3.0 以降のデバイスはどれも対応
していますが、必ずしも Filter がかかるとは限らないようです。
下記はいくつかテストした結果です。

                               depth-tex sh-samplers PCF Filter
----------------------------------------------------------------
8064 Adreno 320 OpenGL ES 3.0      ◎        ◎      ◎   --
8064 Adreno 320 OpenGL ES 2.0      ◎        --      --   --
Mali-T604       OpenGL ES 3.0      ◎        ◎      ◎   ◎
Tegra 4         OpenGL ES 2.0      ◎        ◎      ◎   ◎
Tegra 3         OpenGL ES 2.0      --        --      --   --
iOS PVR 543MP3  OpenGL ES 2.0      ◎        ◎      ◎   ◎
Vivante GC4000  OpenGL ES 2.0      ◎        --      --   --
Mali-400MP4     OpenGL ES 2.0      ◎        --      --   --
PowerVR SGX540  OpenGL ES 2.0      ◎        --      --   --

この辺りはもう少し詳しく調べたいと思っています。
なお Tegra4 の Extension 詳細は下記のページに追加しました。

CPU/GPU OpenGL ES Extension (Mobile GPU)

関連エントリ
Android OpenGL ES と V-Sync (eglSwapInterval)
Nexus 10 GPU Mali-T604
Qualcomm APQ8064 GPU Adreno 320 の速度
さらに OpenGL ES 2.0 Mobile GPU の速度比較
GPU 速度に関連するエントリ

Android Qualcomm Snapdragon 800 MSM8974 Krait 400 の速度

CPU ベンチに Snapdragon 800 MSM8974 Krait 400 の結果を追加しました。

ARM CPU core 毎の浮動小数点演算速度の比較 (VFP/NEON)
CPU benchmark

浮動小数点演算命令毎の実行速度

                (1)      (2)      (3)      (4)       (5)      (6)      (7)
               Nexus7   iPad4    HTL21   Nexus10  iPhone5s iPhone5s KindleHDX7
              Cortex-A9 Swift    Krait  Cortex-A15 Cyclone  Cyclone   Krait4
               Tegra3    A6X    APQ8064  Exynos5D   A7 32    A7 64   MSM8974
               1.2GHz   1.4GHz   1.5GHz   1.7GHz    1.3GHz   1.3GHz   2.2GHz
------------------------------------------------------------------------------
a:m44 vmla_AQ  3.959    1.204    1.337    0.619     0.700    -----    0.661
b:m44 vmla_BQ  2.002    1.266    0.931    0.569     0.670    -----    0.542
c:m44 vmla_AD  3.980    1.554    1.889    0.557     0.649    -----    0.888
d:m44 vmla_BD  2.003    1.238    1.532    0.568     0.745    -----    0.768
A:m44 vfma_AQ  -----    1.519    1.882    0.746     0.707    0.692    1.178
B:m44 vfma_BQ  -----    1.484    0.695    0.840     0.699    0.696    0.463
e:fadds     A  3.343    2.878    2.774    2.383     3.551    1.043    1.864
f:fmuls     A  3.337    2.953    2.747    2.369     3.475    1.548    1.867
g:fmacs     A  3.337    5.757    5.574    2.956     3.480    -----    2.052
h:vfma.f32  A  -----    5.756    2.747    2.957     3.480    3.185    1.864
i:vadd.f32 DA  3.426    2.877    2.762    1.183     1.031    1.031    1.866
j:vmul.f32 DA  3.421    2.950    2.746    1.478     1.545    1.545    1.864
k:vmla.f32 DA  3.792    2.951    5.604    1.480     1.567    -----    2.051
o:vfma.f32 DA  -----    2.494    2.833    1.479     1.574    1.753    1.871
l:vadd.f32 QA  6.688    2.878    2.801    2.365     1.031    1.039    1.872
m:vmul.f32 QA  6.681    2.952    2.761    2.364     1.548    1.548    1.879
n:vmla.f32 QA  6.681    2.950    5.606    2.367     1.574    -----    2.059
N:vfma.f32 QA  -----    -----    -----    -----     -----    1.696    -----
p:fadds     B  3.347    5.756    3.467    2.956     6.953    3.663    -----
q:fmuls     B  4.195    5.756    3.556    3.558     6.652    3.296    -----
r:fmacs     B  6.688   11.514    6.298    5.912     9.867    -----    -----
s:vfma.f32  B  -----   11.513    3.430    5.910     9.859    3.292    -----
t:vadd.f32 DB  3.421    2.881    3.529    2.958     3.663    3.643    1.865
u:vmul.f32 DB  3.422    2.949    3.447    2.364     3.114    3.289    2.339
v:vmla.f32 DB  7.561    5.755    6.293    4.728     6.185    -----    3.773
z:vfma.f32 DB  -----    5.755    3.437    4.730     6.188    6.237    2.340
w:vadd.f32 QB  6.705    2.879    3.457    2.961     3.659    3.641    1.875
x:vmul.f32 QB  6.683    2.950    3.428    2.363     3.101    3.276    2.340
y:vmla.f32 QB  7.532    5.759    6.372    4.729     6.199    -----    3.746
Y:vfma.f32 QB  -----    -----    -----    -----     -----    6.226    -----

・↑数値は実行時間(秒) 数値が小さい方が高速。single thread
・すべて単精度 32bit float の演算です。

Krait 400 は動作 clock が高いこともあり非常に高速です。
上の結果では同じ ARMv7A VFPv4 世代の Cortex-A15 に匹敵し、
実行効率の差を動作クロックが十分補っていることがわかります。

またここでの Quad core は Cortex-A9, Krait, Krait 400 だけなので、
総合的なパフォーマンスでは高クロックかつ Quad core の Krait 400 が
最も高いスコアになることが予想できます。

NEON 命令は 64bit と 128bit の差がなく、Cortex-A15 と違い 128bit
単位となっています。

vfma (FMA) よりも vmla が 2倍遅かった Krait 無印 (3) と比べて、
Krait 400 (7) では vmla も vfma に近い速度が出ています。
同じ Krait でも傾向が異なっており、様々な改良が施されているようです。

同時にあらためて A7 Cyclone の単 core 性能が非常に高いこともわかります。
A7 Cyclone の結果は 2個ありますが、
(5) は ARMv8 AArch32 (armv7) 32bit モードの結果で
(6) は ARMv8 AArch64 (arm64) 64bit モードでの結果です。

以下テスト端末の詳細

device                     OS   SoC      CPU core     clock  Arch        VFP
----------------------------------------------------------------------------
(1)ASUS Nexus 7 (2012)     A4.2 Tegra 3  Cortex-A9 x4 1.2GHz ARMv7A 32bit v3
(2)Apple iPad 4            i6.1 A6X      Swift     x2 1.4GHz ARMv7A 32bit v4
(3)HTC J butterfly HTL21   A4.1 APQ8064  Krait     x4 1.5GHz ARMv7A 32bit v4
(4)Samsung Nexus 10        A4.2 Exynos5D Cortex-A15x2 1.7GHz ARMv7A 32bit v4
(5)Apple iPhone 5s         i7.0 A7       Cyclone   x2 1.3GHz ARMv8A 32bit v4
(6)Apple iPhone 5s         i7.0 A7       Cyclone   x2 1.3GHz ARMv8A 64bit Ad
(7)Amazon Kindle Fire HDX7 A4.2 MSM8974  Krait 400 x4 2.2GHz ARMv7A 32bit v4

下記はもうひとつのCPUベンチの結果です。

  SoC CPU              clock  compiler  arch   time  MB/s   MBS/GHz
-------------------------------------------------------------------
1.A7 Cyclone + AES     1.3GHz clang 5.0 arm64  0.129 837.54  644.26
2.A7 Cyclone           1.3GHz clang 5.0 arm64  1.04  104.27   80.21
3.A7 Cyclone           1.3GHz clang 5.0 armv7  1.16   93.04   71.57
4.MSM8974 Krait 400    2.2GHz gcc 4.8   armv7  1.41   76.67   34.85
5.Exynos 5D Cortex-A15 1.7GHz gcc 4.6   armv7  1.49   72.61   42.71
6.A6X Swift            1.4GHz clang 4.2 armv7  1.75   61.82   44.16
7.APQ8064 Krait        1.5GHz gcc 4.6   armv7  2.28   47.64   31.82
8.Tegra3 Cortex-A9     1.3GHz gcc 4.4.3 armv7  3.00   36.15   25.82

・time の単位は秒
・MB/s が大きいほうが高速
・MBS/GHz = 1GHz あたりの処理速度

専用命令を使っている 1. が一桁高速なのは当然ですが、64bit アーキテクチャ
の A7 も十分高速です。
新 core + クロック数が最も高い Krait 400 はそれらに次ぐ速度となりました。
テスト内容の詳細はこちらから。

テストに使った Kindle Fire HDX 7 のデータは下記にも追加しました。

CPU/GPU OpenGL ES Extension (Mobile GPU)

関連エントリ
iPhone 5s A7 CPU の浮動小数点演算速度 (2) (arm64/AArch64/64bit)
iPhone 5s A7 CPU の浮動小数点演算速度 (32bit)
Nexus 10 CPU Cortex-A15 の速度
Qualcomm APQ8064 GPU Adreno 320 の速度
Qualcomm APQ8064 Krait/A6 swift の浮動小数点演算能力

Android OpenGL ES 2.0 と 3.0 の切り替え

Desktop の OpenGL 4.x との互換性を考えるならば、
OpenGL ES 3.0 の方が圧倒的に相性が良いです。
DirectX で例えるなら Direct3D11/10 と Direct3D9 を比べるようなもの。
Direct3D11 (OpenGL4) と Direct3D10 (OpenGL ES 3.0) は同じ API 構造を
保っていますが Direct3D9 (OpenGL ES 2.0) は大きく異なります。

OpenGL は DirectX ほどの違いはなく API 上は上位互換性を保っています。
ですが Shader の構文や描画パイプラインの設計は、やはりどちらかに
合わせる必要があります。

設計が大きく異なるならば、OpenGL ES 2.0 と OpenGL ES 3.0 のバイナリを
完全に分けてしまった方が良いのかもしれません。

以前 NDK の dll を分離する方法を紹介しました。

Android NDK の初期化と dll の分離

もし dll を分割して 2段階で読み込んでいるなら、同じ方法で
バイナリを切り替えることができます。
例えば下記のように。

・libjniproxy.so
・libappmain_es2.so
・libappmain_es3.so

関連エントリ
Android OpenGL ES 3.0 対応 GPU を判定する方法
Android 4.4 Adreno 320 の OpenGL ES 3.0 と Version 判定
Android NDK の初期化と dll の分離