Nexus10 を入手したので ARMv7A の新しい CPU core 3種類が揃いました。
Apple Swift, Qualcomm Krait, ARM Cortex-A15 を比べてみます。
動作クロックが一番高いせいもありますが、
Cortex-A15 の動作は Swift よりもさらに高速でした。
(1) (2) (3) (4) (5) (6) (7) iPad3 Nexus7 EVO 3D iPhone5 iPad4 HTL21 Nexus10 A5X Tegra3 MSM8660 A6 A6X APQ8064 Exynos5D ARM A9 ARM A9 Scorpion Swift Swift Krait ARM A15 1.0GHz 1.2GHz 1.2GHz 1.3GHz? 1.4GHz? 1.5GHz 1.7GHz VFPv3 VFPv3 VFPv3 VFPv4 VFPv4 VFPv4 VFPv4 ---------------------------------------------------------------------- a:m44 vmla_AQ 4.784 3.959 2.859 1.293 1.204 1.337 0.619 b:m44 vmla_BQ 2.408 2.002 1.136 1.359 1.266 0.931 0.569 c:m44 vmla_AD 4.781 3.980 3.053 1.669 1.554 1.889 0.557 d:m44 vmla_BD 2.406 2.003 1.434 1.329 1.238 1.532 0.568 A:m44 vfma_AQ ----- ----- ----- 1.632 1.519 1.882 0.746 B:m44 vfma_BQ ----- ----- ----- 1.594 1.484 0.695 0.840 e:fadds A 4.010 3.343 3.383 3.090 2.878 2.774 2.383 f:fmuls A 4.010 3.337 3.383 3.167 2.953 2.747 2.369 g:fmacs A 4.012 3.337 3.379 6.180 5.757 5.574 2.956 h:vfma.f32 A ----- ----- ----- 6.180 5.756 2.747 2.957 i:vadd.f32 DA 4.111 3.426 3.377 3.091 2.877 2.762 1.183 j:vmul.f32 DA 4.110 3.421 3.383 3.168 2.950 2.746 1.478 k:vmla.f32 DA 4.512 3.792 3.380 3.166 2.951 5.604 1.480 l:vadd.f32 QA 8.023 6.688 3.377 3.090 2.878 2.801 2.365 m:vmul.f32 QA 8.022 6.681 3.384 3.166 2.952 2.761 2.364 n:vmla.f32 QA 8.025 6.681 3.380 3.167 2.950 5.606 2.367 o:vfma.f32 DA ----- ----- ----- 3.167 2.494 2.833 1.479 p:fadds B 4.014 3.347 5.917 6.181 5.756 3.467 2.956 q:fmuls B 5.013 4.195 5.917 6.180 5.756 3.556 3.558 r:fmacs B 8.023 6.688 8.451 12.361 11.514 6.298 5.912 s:vfma.f32 B ----- ----- ----- 12.363 11.513 3.430 5.910 t:vadd.f32 DB 4.113 3.421 5.916 3.090 2.881 3.529 2.958 u:vmul.f32 DB 4.118 3.422 5.073 3.169 2.949 3.447 2.364 v:vmla.f32 DB 9.027 7.561 8.451 6.180 5.755 6.293 4.728 w:vadd.f32 QB 8.021 6.705 5.916 3.090 2.879 3.457 2.961 x:vmul.f32 QB 8.029 6.683 5.074 3.167 2.950 3.428 2.363 y:vmla.f32 QB 9.026 7.532 8.457 6.179 5.759 6.372 4.729 z:vfma.f32 DB ----- ----- ----- 6.181 5.755 3.437 4.730 ---------------------------------------------------------------------- ↑数値は実行時間(秒) 数値が小さい方が速い (1)=Apple iPad 3 A5X Cortex-A9 x2 1.0GHz VFPv3 i6.1 (2)=ASUS Nexus 7 Tegra 3 Cortex-A9 x4 1.2GHz VFPv3 A4.2 (3)=HTC EVO 3D ISW12HT MSM8660 Scorpion x2 1.2GHz VFPv3 A4.0 (4)=Apple iPhone 5 A6 Swift x2 1.3GHz? VFPv4 i6.1 (5)=Apple iPad 4 A6X Swift x2 1.4GHz? VFPv4 i6.1 (6)=HTC J butterfly HTL21 APQ8064 Krait x4 1.5GHz VFPv4 A4.1 (7)=Samsung Nexus 10 Exynos5D Cortex-A15 x2 1.7GHz VFPv4 A4.2
テスト項目の詳細は下記参照 (a:~z:)
・Qualcomm APQ8064 Krait/A6 swift の浮動小数点演算能力
iPad4/EVO 3D/Butterfly は計測しなおしたため以前よりも数値が上がっています。
a:~d: を見ると 1.7GHz の Cortex-A15 は Swift の倍近い数値となっています。
命令単体でも効率が上がっており、Krait と比べても 64bit D (float2) 命令は
クロック差以上の速度となっています。
64bit D (float2) と 128bit Q (float4) に差があることから、おそらく
Cortex-A15 は 64bit 単位の ALU が 2 pipe 存在しているのではないでしょうか。
128bti Q (float4) 時の速度は Swift/Krait と大きな違いがないので
演算能力のピークレートは自体は Swift/Krait と同一でしょう。
D, Q の差がない Scorpion/Swift/Krait は 128bit 単位だと考えられます。
(1)~(3) Cortex-A9/Scorpion の a:~d: では AQ/AD と BQ/BD の結果に
大きな違いが生じています。
これが CPU 世代間の違いとなっており、(4)~(7) の Swift/Krait/Cortex-A15
では命令順に依存せずに一定の効率で実行できている事がわかります。
以前も書いたとおり Swift はスカラーの積和命令だけ遅くなっています。
NEON のベクターでは積和でも特に速度が落ちていないため、
何らかの構造的な理由によるものと思われます。
同じように Krait にも苦手なパターンがあります。
ARM では VFPv4 以降 FMA (Fused Multiply add) 命令が追加されています。
Krait は vfma (FMA) よりも従来の vmla 命令が倍近く遅くなっています。
中間丸め込みを行うために vmul + vadd に展開されている可能性があります。
●Krait 最適化
a:~d: の演算は vmla を使っていますが、この命令は Krait では低速となっています。
vfma に置き換えることで高速化できる可能性があるので試してみました。
// A: mat44 neon_AQ の vfma 化 vmul.f32 q8, q0, d8[0] vlma.f32 q8, q1, d8[1] vlma.f32 q8, q2, d9[0] vlma.f32 q8, q3, d9[1] : ↓ vmul.f32 q8, q0, d8[0] vdup.f32 q9, d8[1] vfma.f32 q8, q1, q9 vdup.f32 q10, d9[0] vfma.f32 q8, q2, q10 vdup.f32 q11, d9[1] vfma.f32 q8, q3, q11 :
// B: mat44 neon_AQ の vfma 化 vmul.f32 q8, q0, d8[0] vmul.f32 q9, q0, d10[0] vmul.f32 q10, q0, d12[0] vmul.f32 q11, q0, d14[0] vmla.f32 q8, q1, d8[1] vmla.f32 q9, q1, d10[1] vmla.f32 q10, q1, d12[1] vmla.f32 q11, q1, d14[1] : ↓ vmul.f32 q8, q0, d8[0] vmul.f32 q9, q0, d10[0] vmul.f32 q10, q0, d12[0] vmul.f32 q11, q0, d14[0] vdup.32 q12, d8[1] vdup.32 q13, d10[1] vdup.32 q14, d12[1] vdup.32 q15, d14[1] vfma.f32 q8, q1, q12 vfma.f32 q9, q1, q13 vfma.f32 q10, q1, q14 vfma.f32 q11, q1, q15 :
vfma は vmla と違い vector * scalar ができないので、
単純に置換するだけでは動きません。
SSE と同じようにデータのコピーが必要となるので vdup を挿入しています。
ARM A9 ARM A9 Scorpion Swift Swift Krait ARM A15 ---------------------------------------------------------------------- a:m44 vmla_AQ 4.784 3.959 2.859 1.293 1.204 1.337 0.619 b:m44 vmla_BQ 2.408 2.002 1.136 1.359 1.266 0.931 0.569 ↓ A:m44 vfma_AQ ----- ----- ----- 1.632 1.519 1.882 0.746 B:m44 vfma_BQ ----- ----- ----- 1.594 1.484 0.695 0.840
A: はかなり遅いですが、B: は効果がありました。
このケースでは Krait が Cortex-A15 を超えています。
予想通り Swift , Cortex-A15 にとっては逆効果で、vdup が増えた分だけ遅くなりました。
なお vmla と vfma は丸め込みのタイミングが異なるので厳密には結果は一致しません。
vfma の方が誤差が少ないのですが、Cのコードで普通に書くと fmacs になるので
検証コードで見事に assert に引っかかりました。
関連エントリ
・2013/01/09:Qualcomm APQ8064 GPU Adreno 320 の速度
・2012/12/23:Qualcomm APQ8064 Krait/A6 swift の浮動小数点演算能力