※ 이 글은 오가사와라 히로유키(小笠原博之) 씨가 블로그에 적은 글을 번역한 것입니다. 사정에 따라 예고없이 삭제될 수 있으므로 양해부탁드립니다.
iPhone 5s A7 CPU의 부동소수점 연산속도(2) (AArch64/64bit)
(원문 : iPhone 5s A7 CPU の浮動小数点演算速度 (2) (AArch64/64bit))
64bit mode (AArch64)에서 테스트해봤습니다. 명령도 레지스터 구조도 다르므로 다른 코드를 썼습니다. 검증이 불완전하기에 이 결과에 잘못된 부분이 들어가 있을 가능성이 있습니다.
(1) (2) (3) (4) (5) iPhone5 HTL21 Nexus10 iPhone5s iPhone5s Swift Krait Cortex-A15 AArch32 AArch64 A6 APQ8064 Exynos5D A7 A7 1.3GHz 1.5GHz 1.7GHz 1.3GHz? 1.3GHz? -------------------------------------------------------------------- a:m44 vmla_A Q 1.293 1.337 0.619 0.700 ----- b:m44 vmla_B Q 1.359 0.931 0.569 0.670 ----- c:m44 vmla_A D 1.669 1.889 0.557 0.649 ----- d:m44 vmla_B D 1.329 1.532 0.568 0.745 ----- A:m44 vfma_A Q 1.632 1.882 0.746 0.707 0.692 (fmla v) B:m44 vfma_B Q 1.594 0.695 0.840 0.699 0.696 (fmla v) e:fadds A 3.090 2.774 2.383 3.551 1.043 (fadd s) f:fmuls A 3.167 2.747 2.369 3.475 1.548 (fmul s) g:fmacs A 6.180 5.574 2.956 3.480 ----- h:vfma.f32 A 6.180 2.747 2.957 3.480 3.185 (fmadd s) i:vadd.f32 D A 3.091 2.762 1.183 1.031 1.031 (fadd.2s) j:vmul.f32 D A 3.168 2.746 1.478 1.545 1.545 (fmul.2s) k:vmla.f32 D A 3.166 5.604 1.480 1.567 ----- o:vfma.f32 D A 3.167 2.833 1.479 1.574 1.753 (fmla.2s) l:vadd.f32 Q A 3.090 2.801 2.365 1.031 1.039 (fadd.4s) m:vmul.f32 Q A 3.166 2.761 2.364 1.548 1.548 (fmul.4s) n:vmla.f32 Q A 3.167 5.606 2.367 1.574 ----- *:vfma.f32 Q A ----- ----- ----- ----- 1.696 (fmla.4s) p:fadds B 6.181 3.467 2.956 6.953 3.663 (fadd s) q:fmuls B 6.180 3.556 3.558 6.652 3.296 (fmul s) r:fmacs B 2.361 6.298 5.912 9.867 ----- s:vfma.f32 B 2.363 3.430 5.910 9.859 3.292 (fmadd s) t:vadd.f32 D B 3.090 3.529 2.958 3.663 3.643 (fadd.2s) u:vmul.f32 D B 3.169 3.447 2.364 3.114 3.289 (fmul.2s) v:vmla.f32 D B 6.180 6.293 4.728 6.185 ----- z:vfma.f32 D B 6.181 3.437 4.730 6.188 6.237 (fmla.2s) w:vadd.f32 Q B 3.090 3.457 2.961 3.659 3.641 (fadd.4s) x:vmul.f32 Q B 3.167 3.428 2.363 3.101 3.276 (fmul.4s) y:vmla.f32 Q B 6.179 6.372 4.729 6.199 ----- *:vfma.f32 Q B ----- ----- ----- ----- 6.226 (fmla.4s) ↑수치는 실행시간(초) 수치가 작을수록 고속
scalar 연산은 예상대로 AArch64 쪽이 고속으로 실행되는 것 같습니다. AArch64에서는 vector 때와 동등하여 NEON에 통합되었다고 예상됩니다.
ARMv8의 AArch64에서는 SIMD 레지스터의 구조가 변하여, 전부 128bit 사이즈가 되었습니다. 스칼라 연산은 그 일부만을 이용하는 구조로, x86의 SSE와 정확하게 같은 방식입니다. 스칼라를 로드할 때에도 레지스터 전체가 클리어됩니다.
32bit (ARMv7)에서는 Q(128bit) x 8 = D(64bit) x 16 = S(32bit) x 32가 같은 영역이었습니다. D는 S의 2개분이고, Q에는 S레지스터가 4개 포함되어 있습니다.
AArch32의 경우, 스칼라 연산은 레지스터의 일부 다시 쓰기에 해당되기에 그 때문에 파이프라인 실행효율이 떨어지는 것이라 예상됩니다.
fmadd가 느린 경향은 Swift와 같습니다. AArch64에서는 이 명령만 4 오퍼랜드였습니다.
A: 와 B: 는 다음과 같습니다.
; A: m44 fmla A Q ldp q0, q1, [%0] ldp q2, q3, [%0,#32] ldp q4, q5, [%1] ldp q6, q7, [%1,#32] fmul.4s v8, v0, v4[0] fmla.4s v8, v1, v4[1] fmla.4s v8, v2, v4[2] fmla.4s v8, v3, v4[3] str q8, [%2] 〜 fmul.4s v8, v0, v7[0] fmla.4s v8, v1, v7[1] fmla.4s v8, v2, v7[2] fmla.4s v8, v3, v7[3] str q8, [%2,#48]
; B: m44 fmla B Q ldp q0, q1, [%0] ldp q4, q5, [%1] ldp q6, q7, [%1,#32] fmul.4s v8, v0, v4[0] fmul.4s v9, v0, v5[0] fmul.4s v10, v0, v6[0] fmul.4s v11, v0, v7[0] ldp q2, q3, [%0,#32] 〜 fmla.4s v8, v3, v4[3] fmla.4s v9, v3, v5[3] fmla.4s v10, v3, v6[3] fmla.4s v11, v3, v7[3] stp q8, q9, [%2] stp q10, q11, [%2,#32]
레지스터 번호가 일치하므로 굉장히 쓰기 쉬워졌습니다.