日別アーカイブ: 2011年7月15日

ARM cpu vfp の種類と fp16 命令を使ってみる

ARMv7 の fpu、vfp には大きく分けて NEON 命令のありなしで 2種類あります。
細かい違いを含めると更に増えます。
gcc のオプションを見るとこんな感じ。

vfp
vfpv3
vfpv3-d16
vfpv3-fp16
vfpv3-d16-fp16
neon
neon-fp16
vfpv4
vfpv4-d16
neon-vfpv4

使える機能はハードウエアレジスタ MVFR0/MVFR1 を見ることで判断できる
ようです。分かる範囲でまとめてみました。

ARM vfp の種類

                     D32 VSP VDP DIV SQR SV  NLS NI  NSP NHP VHP FMA
--------------------------------------------------------------------
Cortex-A8 vfpv3+NEON  ◎  ◎  ◎  ◎  ◎  ◎  ◎  ◎  ◎  --  --  --
Cortex-A9 vfpv3-D16   --  ◎  ◎  ◎  ◎  ◎  --  --  --  --  ◎  --
Cortex-A9 vfpv3+NEON  ◎  ◎  ◎  ◎  ◎  --  ◎  ◎  ◎  ◎  ◎  --
Cortex-A5 vfpv4-D16   --  ◎  ◎  ◎  ◎  --  -   --  --  -   ◎  ◎
Cortex-A5 vfpv4+NEON  ◎  ◎  ◎  ◎  ◎  --  ◎  ◎  ◎  ◎  ◎  ◎
--------------------------------------------------------------------

D32 = double 32個
VSP = VFP 単精度演算
VDP = VFP 倍精度演算
DIV = HW 除算
SQR = HW 平方根
SV  = VFP Short Vector 対応
NLS = NEON Load/Store
NI  = NEON Int演算
NSP = NEON 単精度演算
NHP = NEON half(fp16) 演算
VHP = VFP half(fp16) 演算
FMA = IEEE 積和 Fused Multiply Add

Cortex-A9 以降は fp16 (16bit 浮動小数点命令) に対応しています。

vfpv3 と vfpv4 の違いは FMA (Fused Multiply Add) にあるようです。

また VFP の Vector Mode (SV) が Cortex-A9 の NEON 版から無くなっている
こともわかります。この場合 FPSCR の Len が 0 以外の場合例外が発生し、
ソフトウエアでエミュレーションすることになるようです。

Cortex-A9 で fp16 命令を試してみました。
下記の命令で 16bit, 32bit float の相互変換ができます。

vcvtb.f16.f32  sd, ss
vcvtt.f16.f32  sd, ss
vcvtb.f32.f16  sd, ss
vcvtt.f32.f16  sd, ss

Android NDK ではオプション指定してもコンパイルできませんでしたが、
iOS ではコンパイルが通りました。

unsigned int SingleToHalf( float a, float b )
{
    float    fparam[4];
    fparam[0]= a;
    fparam[1]= b;
    __asm__ __volatile__(
        "vldmia %0, {d0-d1}\n"
        "vcvtb.f16.f32  s2, s0\n"
        "vcvtt.f16.f32  s2, s1\n"
        "vstmia %0, {d0-d1}\n"
         : "=&r"( fparam )
         : "0"( fparam )
         : "d0","d1","cc" );
    unsigned int*   iparam= (unsigned int*)fparam;
    return  iparam[2];
}

void HalfToSingle( unsigned int param_in )
{
    unsigned int    iparam[4];
    iparam[0]= param_in;
    __asm__ __volatile__(
        "vldmia %0, {d0-d1}\n"
        "vcvtb.f32.f16  s1, s0\n"
        "vcvtt.f32.f16  s2, s0\n"
        "vstmia %0, {d0-d1}\n"
         : "=&r"( iparam )
         : "0"( iparam )
         : "d0","d1","cc" );
    float*   fparam= (float*)iparam;
    printf( "%f %f\n", fparam[0], fparam[1] );
}

iPad2 (Cortex-A9) で動作し、相互変換できました。
fp16 未対応の iPod touch 3 (Cortex-A8) ではエラーで停止します。

Mobile GPU の比較

PowerVR SGX, Adreno, Tegra2 など 16bit (half) float 対応の GPU は
意外に多いので、頂点フォーマットの変換に使いたい機能です。

関連エントリ
Snapdragon の本当の浮動小数点演算能力
iPad2 A5 と浮動小数演算 VFP/NEON
Tegra2 Cortex-A9 と浮動小数演算
Snapdragon と浮動小数演算速度
ARM Cortex-A8 の NEON と浮動小数演算最適化