ユーザ用ツール

サイト用ツール


app:vfpbench

VFP Benchmark

Android Android iPhone

概要

blog (ホイール欲しい ハンドル欲しい) で記事にしてきた vfp/neon の CPU 速度テストプログラムをアプリにしました。 過去のベンチマークの結果は こちら にまとめています。

もともとこのアプリが作られたきっかけは、Cortex-A8 ではスカラーの浮動小数点演算ユニット VFP の性能が著しく低かったことです。 fmuls, fadds, fmacs などの命令単位で速度を比較すれば一目瞭然で、VFP 命令を使うと他の CPU core の 1/5~1/10 程度の速度しか出ません。 Cortex-A8 では VFP の代わりに NEON 命令 vmul, vadd, vmla を使うことで十分な実行速度を保つことが分かりました。

このベンチマークアプリを使うと、命令単位で CPU core の浮動小数点演算速度やサイクル数を割り出すことができます。 プログラマがコード最適化の方針を決定したり、目標にすることができます。 アプリケーション最適化時のヒントとして活用してください。

またその結果から理論的なピーク値を割り出すことが可能です。 テスト結果を比較することで、演算ユニットのパイプライン構造などもある程度わかってくるかもしれません。 なお純粋に命令の速度を計測することが目的なので、コードはすべてオンキャッシュによる動作が前提となっています。

  • モバイルデバイスの性能を確認する
  • CPU の演算ユニットやパイプラインの特性を調べて最適化に利用する
  • ピーク性能を調べて最適化の目標値にする

ストレージやメモリなど外部 I/O の影響を受けないので、実際のアプリケーションなど実用時の速度結果にはなりませんのでご注意ください。 このテストの結果とシステム全体の速度は必ずしも一致しません。

実際に VFP Benchmark で計測した結果は下記の通り。

注意点: 現在のバージョンでは非対称マルチコア CPU (Cortex-A15 + Cortex-A7 等) の場合、スレッド実行時の結果が正しいものになりませんのでご注意ください。

更新履歴

  • 2019/06/01 v2.0 : console version。big.LITTLE 対応, Loop scale 対応, half-precision fp (fullhp) 対応
  • 2015/07/12 v1.3.5 : x86/x64 FMA3 対応
  • 2015/03/06 v1.3.4 : Android TV 対応
  • 2015/01/18 v1.3.3 : Android 版で MIPS の FPU 命令に対応
  • 2015/01/15 v1.3.2 : Android 2.2/2.3 対応
  • 2014/11/30 v1.3.1 : Android 4.3 以前で動作しなくなっていたバグ修正。default loop 値の調整
  • 2014/11/09 v1.3 : Android 64bit 対応 (arm64-v8a, x86_64, mips64 対応), iOS 版は最初から arm64 対応済み
  • 2014/07/24 Wear : Android Wear 版追加
  • 2014/07/22 v1.2 : Android 版 UI の変更
  • 2014/01/28 v1.1 : Android 版 x86 SSE/AVX 対応, thread 実行時のメモリリーク修正
  • 2014/01/18 v1.0 : 初期版

各テストの詳細

Test 項目

  1. FPU/SIMD single fp (32bit fp) single-thread
  2. FPU/SIMD double fp (64bit fp) single-thread
  3. Matrix 4×4 single-thread
  4. FPU/SIMD single fp (32bit fp) multi-thread
  5. FPU/SIMD double fp (64bit fp) multi-thread
  6. Matrix 4×4 multi-thread

FPU/SIMD Test

命令単位でひたすら意味のない演算しています。 各種 mul, add, multiply-add, fma (fused multiply-add) を個別に計測しています。

Arch iOS Android cmd FPU / SIMD Scalar sp Instructions Scalar dp Instructions SIMD sp Instructions SIMD dp Instructions
ARMv5TE
ARMv6 (armv6) VFPv2 fmuls, fadds, fmacs fmuld, faddd, fmacd
ARMv7A VFPv3-D16 fmuls, fadds, fmacs fmuld, faddd, fmacd
ARMv7A (armv7) VFPv3-D32 / NEON fmuls, fadds, fmacs fmuld, faddd, fmacd vmul.f32, vadd.f32, vmla.f32
ARMv7A (armv7s) VFPv4-D32 / NEON fmuls, fadds, fmacs, vfma.f32 fmuld, faddd, fmacd, vfma.f64 vmul.f32, vadd.f32, vmla.f32, vfma.f32
ARMv8A (arm64) AArch64 / NEON fmul s, fadd s, fmadd s fmul d, fadd d, fmadd d fmul.4s, fadd.4s, fmla.4s fmul.2d, fadd.2d, fmla.2d
x86 (IA-32) SSE2 / AVX1 / FMA3 mulss, addss, vfmaddss mulsd, addsd, vfmaddsd mulps, addps, vmulps, vaddps, vfmaddps mulpd, addpd, vmulpd, vaddpd, vfmaddpd
x64 (x86_64) SSE2 / AVX1 / FMA3 mulss, addss, vfmaddss mulsd, addsd, vfmaddsd mulps, addps, vmulps, vaddps, vfmaddps mulpd, addpd, vmulpd, vaddpd, vfmaddpd
MIPS32-R2 (mips) FPU mul.s, add.s, madd.s mul.d, add.d, madd.d
MIPS64-R6 (mips64) FPU / PS / MSA mul.s, add.s, madd.s mul.d, add.d, madd.d
Arch arithmetic op FMA
ARMv7A VFPv3/v4 3 operand 3 operand (FMA3)
ARMv7A NEON 3 operand 3 operand (FMA3)
ARMv8A AArch64 FPU 3 operand 4 operand (FMA4)
ARMv8A AArch64 NEON 3 operand 3 operand (FMA3)
x86 / x64 3 operand 3 operand (FMA3)
MIPS32/MIPS64 3 operand 4 operand (FMA4)
  • ARMv7A VFPv3 には fma がありません。逆に ARMv8A AArch64 (64bit) では fmadd/fmla が fma になります。
  • SIMD (NEON) の倍精度演算(dp)は ARMv8A (AArch64) 以降の対応です。ARMv7A の NEON や ARMv8A の AArch32 では倍精度演算が出来ません。
  • 2014/01/24 現在 ARMv8A に対応しているのは iOS 版だけとなります。
  • x86/x64 の fma には未だ対応しておりません。その代わり加算器と乗算器を並列実行できるように mul/add の interleave に対応しています。
  • x64 の内容は x86 同様ですがレジスタ数が多いためコードが異なっています。
  • ARMv5TE では Matrix Test のみ実行できます。
  • 現在 MIPS32/MIPS64 の Paired Single (PS), Mips SIMD Architecture (MSA) には非対応です。

blog 記事での Type-A と Type-B はそれぞれ n8 と ns4 に相当します。

ARM VFP (32bit x1) single fp 単精度浮動小数点演算

32bit scalar 演算です。 NEON 非搭載でも実行できます。ARMv7A では VFP の s register を使用。 ARMv8A (arm64) の場合もほぼ同等の命令で計測します。 ただし fmadd 積和命令は ARMv7A の VFP と違い 4 オペランドです。

ARM NEON (32bit x2) single fp 単精度浮動小数点演算

32bit x 2 の SIMD 演算です。ARMv7A では NEON の d register を使用。 ARMv8A (arm64) の場合は v register の .2s 演算命令になります。

ARM NEON (32bit x4) single fp 単精度浮動小数点演算

32bit x 4 の SIMD 演算です。ARMv7A では NEON の q register を使用。 ARMv8A (arm64) では v register に .4s 演算命令になります。

ARM VFP (64bit x1) double fp 倍精度浮動小数点演算

64bit scalar 演算です。 NEON 非搭載でも実行できます。 ARMv7A では VFP の d register を使用。 ARMv8A (arm64) でも同等の命令で演算します。 ただし fmadd 積和命令は ARMv7A の VFP と違い 4 オペランドになります。

ARM NEON (64bit x2) double fp 倍精度浮動小数点演算

64bit x 2 の SIMD 演算です。ARMv7A では 64bit (double float) の NEON 命令はありません。 ARMv8A (arm64) AArch64 では v register の .2d 演算命令となります。

x86/x64 SSE (32bit x1 ) single fp 単精度浮動小数点演算

SSE を使った scalar 演算です。 SSE は 2オペランドのソース破壊転送かつ x86 ではレジスタが少ないため、n8 を再現することができません。 命令の並びが他の CPU や AVX と異なります。

x86/x64 SSE (32bit x4 ) single fp 単精度浮動小数点演算

SSE を使った SIMD 演算です。 SSE は 2オペランドのソース破壊転送なのでテスト項目が異なります。

x86/x64 AVX (32bit x8 ) single fp 単精度浮動小数点演算

AVX を使った SIMD 演算です。 AVX は 3オペランドなので ARM NEON と同等のテスト内容となります。

x86/x64 SSE (64bit x1 ) double fp 倍精度浮動小数点演算

SSE を使った scalar 演算です。 SSE は 2オペランドのソース破壊転送なのでテスト項目が異なります

x86/x64 SSE (64bit x2 ) double fp 倍精度浮動小数点演算

SSE を使った SIMD 演算です。 SSE は 2オペランドのソース破壊転送なのでテスト項目が異なります。

x86/x64 AVX (64bit x4 ) double fp 倍精度浮動小数点演算

AVX を使った SIMD 演算です。 AVX は 3オペランドなので ARM NEON と同等のテスト内容となります。

n8

read register は常に同一です。 8 命令単位で write register を再利用します。

op s0, s8, s9
op s1, s8, s9
op s2, s8, s9
op s3, s8, s9
op s4, s8, s9
op s5, s8, s9
op s6, s8, s9
op s7, s8, s9

ns4

4命令単位の read 依存があります。

op s0, s8, s4
op s1, s8, s5
op s2, s8, s6
op s3, s8, s7
op s4, s8, s0
op s5, s8, s1
op s6, s8, s2
op s7, s8, s3

n1

入出力は固定ですが同じレジスタに書き込み続けます。 read していないので依存はありませんが、rename できない場合著しく効率が落ちることを想定しています。

op s0, s8, s9
op s0, s8, s9
op s0, s8, s9
op s0, s8, s9
op s0, s8, s9
op s0, s8, s9
op s0, s8, s9
op s0, s8, s9

n12

n8 を 12命令単位に増やしたもの。 pipeline が深くレイテンシが大きい場合に差が出ることを想定しています。 n12 の実行効率は高いですが、他のテストよりも命令数が 1.5 倍に増えるので実行時間は長くなります。 ARMv8A (arm64) AArch64 では、q ではなく v register になります。

op q0, q12, q13
op q1, q12, q13
op q2, q12, q13
op q3, q12, q13
op q4, q12, q13
op q5, q12, q13
op q6, q12, q13
op q7, q12, q13
op q8, q12, q13
op q9, q12, q13
op q10, q12, q13
op q11, q12, q13

Matrix 4x4 Test

完全にオンメモリで非現実的だった VFP/NEON Test と違い、 Matrix Test はメモリアクセスを伴う比較的現実味のあるテストを行います。

Matrix 4x4 C code

C++ 言語でそのまま演算しています。 標準の FPU(VFP) が用いられます。

このテストのみ armeabi/x86/mips すべての CPU で動作します。(armeabi は FPU 無し)

ARMv7A Matrix 4x4 NEON 128bit A

A は in-order な cpu では pipeline stoll が発生し、out-of-order な CPU よりも速度が落ちることを想定しています。

vldmia	%0, {d0-d7}
vldmia	%1, {d8-d15}
vmul.f32	q8,q0,d8[0]
vmla.f32	q8,q1,d8[1]
vmla.f32	q8,q2,d9[0]
vmla.f32	q8,q3,d9[1]
vstmia	%2!, {d16,d17}
vmul.f32	q8,q0,d10[0]
vmla.f32	q8,q1,d10[1]
vmla.f32	q8,q2,d11[0]
vmla.f32	q8,q3,d11[1]
vstmia	%2!, {d16,d17}
vmul.f32	q8,q0,d12[0]
vmla.f32	q8,q1,d12[1]
vmla.f32	q8,q2,d13[0]
vmla.f32	q8,q3,d13[1]
vstmia	%2!, {d16,d17}
vmul.f32	q8,q0,d14[0]
vmla.f32	q8,q1,d14[1]
vmla.f32	q8,q2,d15[0]
vmla.f32	q8,q3,d15[1]
vstmia	%2!, {d16,d17}

ARMv7A Matrix 4x4 NEON 128bit B

B は interleave により実行効率が上がることを想定しています。 ただしメモリが遅ければあまり意味が無いかもしれません。

vldmia	%0, {d0-d7}
vldmia	%1, {d8-d15}
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]
vmla.f32	q8,q2,d9[0]
vmla.f32	q9,q2,d11[0]
vmla.f32	q10,q2,d13[0]
vmla.f32	q11,q2,d15[0]
vmla.f32	q8,q3,d9[1]
vmla.f32	q9,q3,d11[1]
vmla.f32	q10,q3,d13[1]
vmla.f32	q11,q3,d15[1]
vstmia	%2, {d16-d23}

ARMv7A Matrix 4x4 NEON 128bit A FMA

ARMv7A (VFPv4) の FMA は scaler x vector ができないため vdup が挿入されています。(ARMv8A AArch64 arm64 では可能です) そのため vmla より命令数が大幅に増えています。

vldmia	%0, {d0-d7}
vldmia	%1, {d8-d15}
vmul.f32	q8,q0,d8[0]
vdup.32		q9, d8[1]
vfma.f32	q8,q1,q9
vdup.32		q10, d9[0]
vfma.f32	q8,q2,q10
vdup.32		q11, d9[1]
vfma.f32	q8,q3,q11
vstmia	%2!, {d16,d17}
vmul.f32	q8,q0,d10[0]
vdup.32		q12, d10[1]
vfma.f32	q8,q1,q12
vdup.32		q13, d11[0]
vfma.f32	q8,q2,q13
vdup.32		q14, d11[1]
vfma.f32	q8,q3,q14
vstmia	%2!, {d16,d17}
vmul.f32	q8,q0,d12[0]
vdup.32		q9, d12[1]
vfma.f32	q8,q1,q9
vdup.32		q10, d13[0]
vfma.f32	q8,q2,q10
vdup.32		q11, d13[1]
vfma.f32	q8,q3,q11
vstmia	%2!, {d16,d17}
vmul.f32	q8,q0,d14[0]
vdup.32		q12, d14[1]
vfma.f32	q8,q1,q12
vdup.32		q13, d15[0]
vfma.f32	q8,q2,q13
vdup.32		q14, d15[1]
vfma.f32	q8,q3,q14
vstmia	%2!, {d16,d17}

ARMv7A Matrix 4x4 NEON 64bit A

128bit Quad ではなく 64bit (Double) 単位で演算を行っています。 64bit ALU の NEON と 128bit ALU の NEON で差が付く可能性を考慮しましたが 目立った差は検出されません。

vldmia	%0, {d0-d7}
vldmia	%1, {d8-d15}
vmul.f32	d16,d0,d8[0]
vmul.f32	d17,d1,d8[0]
vmla.f32	d16,d2,d8[1]
vmla.f32	d17,d3,d8[1]
vmla.f32	d16,d4,d9[0]
vmla.f32	d17,d5,d9[0]
vmla.f32	d16,d6,d9[1]
vmla.f32	d17,d7,d9[1]
vstmia	%2!, {d16,d17}
vmul.f32	d16,d0,d10[0]
vmul.f32	d17,d1,d10[0]
vmla.f32	d16,d2,d10[1]
vmla.f32	d17,d3,d10[1]
vmla.f32	d16,d4,d11[0]
vmla.f32	d17,d5,d11[0]
vmla.f32	d16,d6,d11[1]
vmla.f32	d17,d7,d11[1]
vstmia	%2!, {d16,d17}
vmul.f32	d16,d0,d12[0]
vmul.f32	d17,d1,d12[0]
vmla.f32	d16,d2,d12[1]
vmla.f32	d17,d3,d12[1]
vmla.f32	d16,d4,d13[0]
vmla.f32	d17,d5,d13[0]
vmla.f32	d16,d6,d13[1]
vmla.f32	d17,d7,d13[1]
vstmia	%2!, {d16,d17}
vmul.f32	d16,d0,d14[0]
vmul.f32	d17,d1,d14[0]
vmla.f32	d16,d2,d14[1]
vmla.f32	d17,d3,d14[1]
vmla.f32	d16,d4,d15[0]
vmla.f32	d17,d5,d15[0]
vmla.f32	d16,d6,d15[1]
vmla.f32	d17,d7,d15[1]
vstmia	%2!, {d16,d17}

ARMv8A Matrix 4x4 NEON 128bit A

ARMv8A AArch64 (arm64) では命令もレジスタ名も異なります。 128bit (v/q) レジスタが倍増し、s(32bit), d(64bit), q(128bit) それぞれ 1 対 1 の対応となりました。 また s/d を複数要素まとめて扱う場合はレジスタ名が v になります。

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, v5[0]
fmla.4s	v8, v1, v5[1]
fmla.4s	v8, v2, v5[2]
fmla.4s	v8, v3, v5[3]
str	q8, [%2,#16]
fmul.4s	v8, v0, v6[0]
fmla.4s	v8, v1, v6[1]
fmla.4s	v8, v2, v6[2]
fmla.4s	v8, v3, v6[3]
str	q8, [%2,#32]
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]

ARMv8A Matrix 4x4 NEON 128bit B

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,  v1, v4[1]
fmla.4s	v9,  v1, v5[1]
fmla.4s	v10, v1, v6[1]
fmla.4s	v11, v1, v7[1]
fmla.4s	v8,  v2, v4[2]
fmla.4s	v9,  v2, v5[2]
fmla.4s	v10, v2, v6[2]
fmla.4s	v11, v2, v7[2]
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]

x86/x64 Matrix 4x4 SSE 128bit A

SSE (SSE1) 命令のみ使用しています。 x64 では edx/eax/ecx の代わりに rdx/rax/rcx が用いられます。

レジスタが少ない、2オペランドの破壊転送、積和命令がない、scalar と vector の乗算ができないことから命令数がかなり多くなります。 x64 ではレジスタ数が 2倍になるので、下記の inline assembler code よりも C compiler の builtin/intrinsic の方が高速なコードが生成されるようです。

mov	%[p3], %edx
mov	%[p1], %eax
mov	%[p2], %ecx
movaps	(%eax), %xmm4
movss	(%ecx), %xmm1
shufps	$0, %xmm1, %xmm1
mulps	%xmm4, %xmm1
movaps	16(%eax), %xmm5
movss	4(%ecx), %xmm0
shufps	$0, %xmm0, %xmm0
mulps	%xmm5, %xmm0
addps	%xmm0, %xmm1
movaps	32(%eax), %xmm6
movss	8(%ecx), %xmm0
shufps	$0, %xmm0, %xmm0
mulps	%xmm6, %xmm0
addps	%xmm0, %xmm1
movaps	48(%eax), %xmm7
movss	12(%ecx), %xmm0
shufps	$0, %xmm0, %xmm0
mulps	%xmm7, %xmm0
addps	%xmm0, %xmm1
movaps	%xmm1, (%edx)
movss	16(%ecx), %xmm1
shufps	$0, %xmm1, %xmm1
mulps	%xmm4, %xmm1
movss	20(%ecx), %xmm0
shufps	$0, %xmm0, %xmm0
mulps	%xmm5, %xmm0
addps	%xmm0, %xmm1
movss	24(%ecx), %xmm0
shufps	$0, %xmm0, %xmm0
mulps	%xmm6, %xmm0
addps	%xmm0, %xmm1
movss	28(%ecx), %xmm0
shufps	$0, %xmm0, %xmm0
mulps	%xmm7, %xmm0
addps	%xmm0, %xmm1
movaps	%xmm1, 16(%edx)
movss	32(%ecx), %xmm1
shufps	$0, %xmm1, %xmm1
mulps	%xmm4, %xmm1
movss	36(%ecx), %xmm0
shufps	$0, %xmm0, %xmm0
mulps	%xmm5, %xmm0
addps	%xmm0, %xmm1
movss	40(%ecx), %xmm0
shufps	$0, %xmm0, %xmm0
mulps	%xmm6, %xmm0
addps	%xmm0, %xmm1
movss	44(%ecx), %xmm0
shufps	$0, %xmm0, %xmm0
mulps	%xmm7, %xmm0
addps	%xmm0, %xmm1
movaps	%xmm1, 32(%edx)
movss	48(%ecx), %xmm1
shufps	$0, %xmm1, %xmm1
mulps	%xmm4, %xmm1
movss	52(%ecx), %xmm0
shufps	$0, %xmm0, %xmm0
mulps	%xmm5, %xmm0
addps	%xmm0, %xmm1
movss	56(%ecx), %xmm0
shufps	$0, %xmm0, %xmm0
mulps	%xmm6, %xmm0
addps	%xmm0, %xmm1
movss	60(%ecx), %xmm0
shufps	$0, %xmm0, %xmm0
mulps	%xmm7, %xmm0
addps	%xmm0, %xmm1
movaps	%xmm1, 48(%edx)

x86/x64 Matrix 4x4 AVX 256bit A

AVX (AVX1) の命令のみ使用しています。 x64 では edx/eax/ecx の代わりに rdx/rax/rcx が用いられます。

x86 ではレジスタが少ないですが、レジスタ長が倍なので比較的余裕があります。 2レーン使用し SSE の半分の命令数で 2倍の演算を行っています。 3 operand で非常に使いやすくなっています。 新しい FMA3/4 命令を用いるとさらに短いコードになります。

mov	%[p3], %edx
mov	%[p1], %eax
mov	%[p2], %ecx
vmovups	(%eax), %xmm0
vmovups	16(%eax), %xmm1
vmovups	32(%eax), %xmm2
vmovups	48(%eax), %xmm3
vperm2f128	$0x00, %ymm0, %ymm0, %ymm0
vperm2f128	$0x00, %ymm1, %ymm1, %ymm1
vperm2f128	$0x00, %ymm2, %ymm2, %ymm2
vperm2f128	$0x00, %ymm3, %ymm3, %ymm3
vmovups	(%ecx), %ymm4
vpermilps	$0x00, %ymm4, %ymm5
vmulps		%ymm0, %ymm5, %ymm6
vpermilps	$0x55, %ymm4, %ymm5
vmulps		%ymm1, %ymm5, %ymm5
vaddps		%ymm5, %ymm6, %ymm6
vpermilps	$0xaa, %ymm4, %ymm5
vmulps		%ymm2, %ymm5, %ymm5
vaddps		%ymm5, %ymm6, %ymm6
vpermilps	$0xff, %ymm4, %ymm5
vmulps		%ymm3, %ymm5, %ymm5
vaddps		%ymm5, %ymm6, %ymm6
vmovups		%ymm6, (%edx)
vmovups	32(%ecx), %ymm4
vpermilps	$0x00, %ymm4, %ymm5
vmulps		%ymm0, %ymm5, %ymm6
vpermilps	$0x55, %ymm4, %ymm5
vmulps		%ymm1, %ymm5, %ymm5
vaddps		%ymm5, %ymm6, %ymm6
vpermilps	$0xaa, %ymm4, %ymm5
vmulps		%ymm2, %ymm5, %ymm5
vaddps		%ymm5, %ymm6, %ymm6
vpermilps	$0xff, %ymm4, %ymm5
vmulps		%ymm3, %ymm5, %ymm5
vaddps		%ymm5, %ymm6, %ymm6
vmovups		%ymm6, 32(%edx)

multi-thread

上記の各テストを CPU core の数だけ並列に走らせます。

計測は各スレッドごとに行っているので、スレッド起動タイミングの差は含まれません。 そのため実用に則したベンチマークよりも、比較的理想に近い値が出ると考えられます。(つまり、あまりリアルじゃない)

NVIDIA の Tegra や Intel の TurboBoost など、 Single Thread 時に特別高いクロックで動作する CPU が存在しています。 この場合単純に Single Thread の結果を core 数倍しても正しい値にならないからです。

app/vfpbench.txt · 最終更新: 2019/06/07 20:58 by oga

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki