月別アーカイブ: 2013年9月

iPhone 5s A7 CPU の速度比較 arm64 (ARMv8 AArch64)

下記 CPU ベンチ の結果を更新しました。
この結果だけを見れば iPhone 5 (A6) より約 1.8倍速く、
iPhone 5s は Core2 duo の 1.74GHz 相当となっています。

CPU ベンチ

以下抜粋 (詳細は上記ページを参照してください)

CPU            arch           GHz  time     MB/sec   1GHzあたり
--------------------------------------------------------------
Apple A7 CPU   ARMv8 (arm64)  1.3  1.04s  104.27MB/s   80.21MB
Apple A7 CPU   ARMv8 (armv7s) 1.3  1.16s   93.04MB/s   71.57MB
Cortex-A15     ARMv7A         1.7  1.49s   72.61MB/s   42.71MB
A6 swift       ARMv7A(armv7s) 1.3  1.87s   57.96MB/s   44.58MB
Krait          ARMv7A         1.5  2.28s   47.64MB/s   31.82MB
A5 Cortex-A9   ARMv7A(armv7)  0.8  5.78s   18.76MB/s   23.44MB

Core i7 3930K  x64 (Win+VC)   3.2  0.48s  228.05MB/s   71.26MB
Core i7 3930K  x86 (Win+VC)   3.2  0.50s  216.50MB/s   67.66MB
Core2 duo x64  x64 (Win+VC)   2.4  0.75s  143.56MB/s   59.81MB
Core2 duo x86  x86 (Win+VC)   2.4  0.85s  127.99MB/s   53.33MB
Atom N270      x86 (Win+VC)   1.6  4.21s   25.74MB/s   16.09MB

 ・「MB/sec」が大きいほうが高速
 ・「1GHzあたり」は同一 CPU クロックでの比較

前回のテストと異なり浮動小数点演算を含んでいません。
それでもやはり 32bit (AArch32) よりも 64bit (AArch64) の方が速くなっており、
公称値である “A6 の 2倍” に近い結果が得られました。

クロック差があるにも関わらず Core2 時代の PC と比較できる域に達しており、
少々信じられませんが clock あたりの実行効率は Core i クラスとなっています。

ただしリンク先にも書いていますが、結果にはコンパイラの性能差や実行環境の
違いも含まれている点に注意してください。
x86/x64 は VC より clang の方が高いスコアになっているので、
実際にはもう少し差が広がるものと考えられます。

またこのスコアはベンチマーク用のものです。
ARMv8 には x86/x64 と同じように AES 専用命令が搭載されていますので、
実用レベルではもっと桁違いに高速に実行できます。

ARMv8 の AES 命令を使った場合のベンチマークスコアはまだ計測できておりません。
余裕があればもう少し幅広くテストしてみたいと思います。

関連エントリ
iPhone 5s A7 CPU の浮動小数点演算速度 (2) (arm64/AArch64/64bit)
Nexus 10 CPU Cortex-A15 の速度
Nexus 10 CPU Cortex-A15 の浮動小数点演算速度
iPad 4/iPad mini A6X/A5 の CPU/GPU 速度
iPhone 5 / A6 の CPU 速度 その 3
benchmark 関連
CPU benchmark

Mac OS X で OpenGL の描画 (Xcode5/retina)

OpenGL の描画までの手順は、サンプル GL3_Text と下記のページを
参考にさせていただきました。

white wheelsのメモ: Cocoaサンプル – OpenGLで描画

Mac Developer Library: GL3 Text

Xcode 上で UI とオブジェクトの対応付けを行っていくスタイルのようです。
GLK はありますが GLKView はなく NSOpenGLView が用いられています。

Xcode 5 で OS X 用のプロジェクト “Cocoa Application” を作成。
MainMenu.xib を選択して、GL3_Text を真似てシーンを作ってみます。

Window → View の下に Custom View をぶら下げます。
名称をとりあえず “GLView” に変更。

xcode_gl01.png

右サイドの Custom Class にも “GLView” と書き込んでおきます。

xcode_gl02.png

プロジェクトには OpenGL.framework を追加しておきます。

GLView.h を作成。

// GLView.h
#import 

@interface GLView : NSOpenGLView
@end

続いて GLView.mm を作成。

// GLView.mm
#import "GLView.h"

@interface GLView() {
    NSTimer*    mpTimer;
}

- (id)initWithFrame:(NSRect)frameRect;
- (void)reshape;
- (void)render;
@end

@implementation GLView

- (id)initWithFrame:(NSRect)frameRect
{
    mpTimer= NULL;

    static const NSOpenGLPixelFormatAttribute	attr[]= {
        NSOpenGLPFADoubleBuffer,
        NSOpenGLPFAAccelerated,
        NSOpenGLPFAColorSize,	24,
        NSOpenGLPFAAlphaSize,	8,
        NSOpenGLPFADepthSize,	24,
        NSOpenGLPFAStencilSize,	8,
        NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
        0
    };

    NSOpenGLPixelFormat*  format= [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
    self= [super initWithFrame:frameRect pixelFormat:format];

    if( self ){

        // (1) Retina 対応
        [self setWantsBestResolutionOpenGLSurface:YES];

        mpTimer= [NSTimer timerWithTimeInterval:1.0/60.0
            target:self
            selector:@selector(render)
            userInfo:self
            repeats:true];
        if( mpTimer ){
            [[NSRunLoop currentRunLoop] addTimer:mpTimer forMode:NSRunLoopCommonModes];
        }
    }
    format= nil;
    return  self;
}

- (void)prepareOpenGL
{
    [super prepareOpenGL];

    GLint  vsync= GL_TRUE;
    [[self openGLContext] setValues:&vsync forParameter:NSOpenGLCPSwapInterval];

    [[self openGLContext] makeCurrentContext];

    // 〜 (2) OpenGL 初期化
}

- (void)update
{
    [super update];
}

- (void)reshape
{
    [super reshape];

    NSRect  brect= [self bounds];
    // (1.1) Retina 対応
    NSRect  rrect= [self convertRectToBacking:brect];

    float   width= rrect.size.width;
    float   height= rrect.size.height;

    // 〜 (3) screen サイズ設定など

}

- (void)drawRect:(NSRect)rect
{
}

- (void)render
{
    [[self openGLContext] makeCurrentContext];

    // 〜 (4) OpenGL の描画

    [[self openGLContext] flushBuffer];
}

- (BOOL)isOpaque
{
    return  YES;
}

Buffer Object の作成や Shader のコンパイルは (2) で行います。
(4) が実際の描画です。 glClear() 〜 glDrawElements() など。
(3) は Window のリサイズに合わせて Viewport を再設定し、
必要に応じて Projection Matrix 等を作り直します。

Retina Display に対応するには (1) の
[self setWantsBestResolutionOpenGLSurface:YES]
を追加します。

この場合 OpenGL からは 4 倍の解像度に見えることになります。
resize 時もサイズ調整が必要で、(1.1) の
[self convertRectToBacking:brect] が変換を行っています。

同じように Mouse Event 等の座標を GL 座標に合わせるには
[self convertPointToBacking:pos] を使います。

当初 Window の Resize に GLView が追従してきませんでした。
設定を比べた結果、Use Autolayout を外すと View の Autosizing を
設定できるようになりました。

xcode_gl06.png

xcode_gl03.png

wgl/egl のような初期設定がなく NSOpenGLView は非常に簡単でした。
ただし initWithFrame の Profile 指定にあるように OS X 10.8
では OpenGL 3.2 までしか対応していないようです。
NSOpenGLProfileVersion3_2Core は NSOpenGL.h で定義されています。

10.9 から OpenGL 4 対応になるらしいので、GL4 の新しい
機能を使うには OS のサポートを待つ必要があります。

以前 Nexus 7 (Ubuntu) で動かしていたプログラム↓も移植できました。

xcode_gl05.png

iOS7 の世代交代と iPad2/iPad mini の対応画面解像度

iOS7 では iPad mini/iPad 2 の iPhone アプリの解像度が上がっています。
これまでの iOS6 の対応デバイスと対応する画面解像度は下記の通り。

iOS6                  3.5     3.5R     4.0R      HD      HD-R
              RAM   480x320  960x640 1136x640 1024x768 2048x1536
----------------------------------------------------------------
iPhone 3GS    256M    ◎       --       --       --       --
iPhone 4      512M    --       ◎       --       --       --
iPhone 4S     512M    --       ◎       --       --       --
iPhone 5        1G    --       --       ◎       --       --
iPod touch 4  256M    --       ◎       --       --       --
iPod touch 5  512M    --       --       ◎       --       --
iPad2         512M    ◎       --       --       ◎       --
iPad3           1G    --       ◎       --       --       ◎
iPad4           1G    --       ◎       --       --       ◎
iPod mini     512M    ◎       --       --       ◎       --

iPhone 3GS は iOS6 唯一の 3.5inch 非retina デバイスですが、
iPad2/iPad mini も iPhone アプリを起動すると 3.5 非retina 相当の
表示になっていました。

iOS 7.0 は下記の通り。

iOS7                  3.5     3.5R     4.0R      HD      HD-R
               RAM  480x320  960x640 1136x640 1024x768 2048x1536
----------------------------------------------------------------
iPhone 4      512M    --       ◎       --       --       --
iPhone 4S     512M    --       ◎       --       --       --
iPhone 5        1G    --       --       ◎       --       --
iPhone 5c       1G    --       --       ◎       --       --
iPhone 5s       1G    --       --       ◎       --       --
iPod touch 5  512M    --       --       ◎       --       --
iPad2         512M    --       ◎       --       ◎       --
iPad3           1G    --       ◎       --       --       ◎
iPad4           1G    --       ◎       --       --       ◎
iPod mini     512M    --       ◎       --       ◎       --

3.5inch 非retina を表示するデバイスが無くなりました。

iPad2/iPad mini の場合は 1x の等倍切り替えが無い代わりに、
3.5 inch retina 相当で表示されるようになっています。
iPhone の retina 対応ゲームが遊びやすくなりました。
もしアプリを iOS 7 以上専用にするなら開発側の負担も減らすことが出来ます。

同時に iOS7 対応デバイスはどれも RAM 512MB 以上になっています。
その他のスペックは下記の通り。(wikipedia: List of iOS devices)

iOS7           RAM  SoC  CPU            GPU           PVR Series
----------------------------------------------------------------
iPhone 4      512M  A4   Cortex-A8  x1  PowerVR SGX535     5
iPhone 4S     512M  A5   Cortex-A9  x2  PowerVR SGX543MP2  5XT
iPhone 5        1G  A6   Swift      x2  PowerVR SGX543MP3  5XT
iPhone 5c       1G  A6   Swift      x2  PowerVR SGX543MP3  5XT
iPhone 5s       1G  A7   A7 64bit   x2  PowerVR G6430?     6?
iPod touch 5  512M  A5   Cortex-A9  x2  PowerVR SGX543MP2  5XT
iPad2         512M  A5   Cortex-A9  x2  PowerVR SGX543MP2  5XT
iPad3           1G  A5X  Cortex-A9  x2  PowerVR SGX543MP4  5XT
iPad4           1G  A6X  Swift      x2  PowerVR SGX554MP4  5XT
iPod mini     512M  A5   Cortex-A9  x2  PowerVR SGX543MP2  5XT

iPhone 4 以外はすべて Cortex-A9 以上の dula core CPU です。
GPU も同様にiPhone 4 を除いて 5XT の MP となっています。

互換性を考えると iOS7 専用はまだ早いかもしれませんが、
開発時に想定すべきハードウエアスペックは順当に世代交代が進んでいる
ことがわかります。

armv6    ARM11       PVR MBX            4    3G/touch2
armv7    Cortex-A8   PVR SGX535         5    3GS/4/touch3/4/iPad
armv7    Cortex-A9   PVR SGX543MP       5XT  4S/touch5/iPad2/3/mini
armv7s   Swift       PVR SGX543MP/554MP 5XT  5/5c/iPad4
arm64    A7 64bit    PVR 6              6    5s

関連エントリ
iPhone 5s A7 64bit CPU と AArch64 (arm64)
iPhone 5s A7 CPU の浮動小数点演算速度 (2) (AArch64/64bit)
iPhone 5s A7 CPU の浮動小数点演算速度 (32bit)
iPhone 5s の Apple A7 GPU

iPhone 5s A7 64bit CPU と AArch64 (arm64)

スマートフォンが搭載しているメモリ容量は非常に速いペースで増加しています。
下記ページに日本で発売された端末のスペックを集めています。

端末全リスト: 日本で発売されたスマートフォン・タブレット全リスト

ざっと眺めただけでもだいたいこんな感じ↓でしょうか。

2008 年 128MB
2009 年 128MB〜256MB
2010 年 256MB〜512MB
2011 年 512MB〜1GB
2012 年 1GB〜2GB
2013 年 1/2GB〜?

特に Android デバイスで容量増加が著しいことがわかります。
このペースが今後も続くと考えるならば、来年には 32bit プロセッサの
壁にぶつかることになります。

RAM 容量が必要になる原因の一つとして画面の高解像度化が考えられます。
こちらも RAM 増量に負けないペースで進化してきました。

2008 年 128MB           480x320              x1.0
2009 年 128MB〜256MB    480x320〜800x480     x2.5
2010 年 256MB〜512MB    854x480〜1024x768    x5.12
2011 年 512MB〜1GB      854x480〜1280x800    x6.67
2012 年 1GB〜2GB        854x480〜2560x1600   x26.67
2013 年 1/2GB〜?       1280x720〜?

高解像度化に伴いアプリケーションで必要な描画リソース量も増加します。
解像度が高いと CPU 描画が間に合わないので、GPU のサポートも必須となります。
描画やレイヤーの合成など OS が管理する GPU リソースも大幅に
増えているのではないかと考えられます。

それ以外にも多数要因があると思いますが、
プロセッサ全体の性能向上とそれに合わせた要求から、
64bit 化は自然な流れだといえるでしょう。

しかしながら、今一番 RAM 容量が切迫しているのは Android の方です。
iOS は Android のおよそ半分の RAM 容量で動作しているため、
iPhone 5s の A7 が先陣を切ったのはかなり意外だと思いました。

64bit 化のメリットとしてアドレス空間の拡張が挙げられますが、
他にも様々なメリットがあります。
特に 64bit mode は互換性の枷から逃れるための大きなチャンスであり、
64bit 化においてはさまざまなアーキテクチャの変更が行われているようです。

ひとつは命令セットやレジスタなどのハードウエア的なアーキテクチャの
変更で、もうひとつはソフトウエア的な取り決めを再設計可能なことです。
全く使われないけど互換性のために残っている機能とか、
設計が古く都合が悪くなっていた仕様などを切り捨てることが出来ます。
(もちろん 32bit 動作 mode では互換性が保たれます)

ARM はロードストア型の RISC プロセッサですが、ひとつの
インストラクションに複数の機能が盛り込まれた多機能な命令体系でした。
例えば命令フィールドには Condition Code が含まれており、条件付き
実行が可能だったり、ソースオペランドに Shifter が組み込まれているなど
かなり独特です。

AArch64 では全く異なる別の命令セットになっています。
よりシンプルで実用的な設計になったと言われていますが、見たところ
便利そうな少々変わった機能も豊富で、十分 ARM らしいと感じました。

コンパイラの出力コードを比べると、関数によっては 64bit の方が命令数が
減ってコンパクトになっていることに気が付きます。

Nexus 7 の Ubuntu で ARM の abi softfp と hard-float を比べる

上記のように ARMv7 では互換性の問題から softfp (soft-float) が
使われることがありました。
浮動小数点値も関数入出力では一旦整数レジスタを経由しており無駄が発生します。

AArch64 (64bit) ではこのような配慮が不要なので最初から hard-float 相当
となっているようです。

// AArch64
__Z5func3fff:                           ; @_Z5func3fff
; BB#0:
	fadd	s0, s0, s1
	fsub	s0, s0, s2
	ret	lr

__Z5func419__simd128_float32_tS_:       ; @_Z5func419__simd128_float32_tS_
; BB#0:
	fmul.4s	v1, v0, v1
	fadd.4s	v0, v1, v0
	ret	lr

// AArch32
__Z5func3fff:                           @ @_Z5func3fff
@ BB#0:
	vmov	d18, r1, r1
	vmov	d20, r0, r0
	vmov	d16, r2, r2
	vadd.f32	d18, d20, d18
	vsub.f32	d0, d18, d16
	vmov	r0, s0
	bx	lr

__Z5func419__simd128_float32_tS_:       @ @_Z5func419__simd128_float32_tS_
@ BB#0:
	vmov	d17, r2, r3
	vmov	d16, r0, r1
	mov	r0, sp
	vld1.32	{d18, d19}, [r0]
	vmul.f32	q9, q8, q9
	vadd.f32	q8, q9, q8
	vmov	r0, r1, d16
	vmov	r2, r3, d17
	bx	lr

64bit 化が直接的な理由ではありませんが、
ABI やスタックフレームの改良ができることも実パフォーマンスに
影響を与えているのではないかと思います。

実際に Windows の x86/x64 でも、両方使っていると
同じ CPU 上でも明らかに 64bit の方が速いことに気が付きます。
64bit が苦手と言われていた Core 2 でもきちんと効果がでていました。

CPU ベンチ

x64 でレジスタ数が倍増したことが一番の要因かもしれませんが、
ABI のようにソフトウエアのデザイン面で互換性保たなくて良いことも
大きなメリットになっていると考えられます。

iPhone のメモリ空間にはまだ余裕がありますが、
パフォーマンスの向上や、利用効率を上げて省電力につなげるという
意味でも iPhone 5s の 64bit 化は意味があるように思います。

昨日 ARMv8 AArch64 の浮動小数点演算速度比較のためにコンパイラの
出力コードを調べていたのですが、これ↓が最初なにかわかりませんでした。

	orr.16b	v5, v1, v1

意味のない or 命令はレジスタ間の move でした。(mov v5,v1)

関連エントリ
iPhone 5s A7 CPU の浮動小数点演算速度 (2) (AArch64/64bit)
iPhone 5s A7 CPU の浮動小数点演算速度 (32bit)
Nexus 7 の Ubuntu で ARM の abi softfp と hard-float を比べる
iPhone 5s の Apple A7 GPU

iPhone 5s A7 CPU の浮動小数点演算速度 (2) (arm64/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 では NEON に統合されていると考えられるため
vector 時と同等になっています。

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]

レジスタ番号が一致しているので非常に書きやすくなりました。

関連ページ
ARM CPU core 毎の浮動小数点演算速度の比較 (VFP/NEON)

関連エントリ
iPhone 5s A7 CPU の浮動小数点演算速度 (32bit)
2013/04/08:Nexus 10 CPU Cortex-A15 の浮動小数点演算速度
2013/01/09:Qualcomm APQ8064 GPU Adreno 320 の速度
2012/12/23:Qualcomm APQ8064 Krait/A6 swift の浮動小数点演算能力