※ 이 글은 오가사와라 히로유키(小笠原博之) 씨가 블로그에 적은 글을 번역한 것입니다. 사정에 따라 예고없이 삭제될 수 있으므로 양해부탁드립니다.

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]

레지스터 번호가 일치하므로 굉장히 쓰기 쉬워졌습니다.

+ Recent posts