Snapdragon 845 の CPU Kryo 385 は ARMv8.2 対応の Cortex-A75 がベースとなっています。前回新しく追加された半精度浮動小数点演算命令を使用してみましたが、他にもいろいろと生成コードに違いがあることがわかりました。そのひとつが atomic 命令です。実際に生成されたコードを比べてみました。


● Atomic 演算

まずは fetch_add() の場合。下記コードのコンパイル結果です。

std::atomic<int>  val( 0 );
val.fetch_add( 10, std::memory_order::memory_order_seq_cst );

x86/x64 では lock prefix 付きの xadd が使われています。

; x64
    lock xaddl  %esi, 8%(rsp)

ARMv7-A の場合 LL/SC 型なので複数の命令に分解されます。ldrex, strex が LL/SC です。途中で同一メモリにアクセスがあると Atomic 操作は失敗するので、失敗していたら loop からやり直します。またメモリアクセスの順序付けが必要な場合はメモリバリア命令 dmb が挿入されます。

; armv7a
loop:
    ldrex  r0, [r4]
    add    r2, r0, #10
    strex  r2, r0, [r4]
    cmp    r2, #0
    bne    loop
    dmb    ish

ARMv8.0 (AArch64) も同様ですが、命令体型はほぼ別ものです。またメモリバリアが命令に組み込まれているので命令数は減っています。ldaxr は ldxr(LL) + acquire に相当し、同じように stlxr は stxr(SC) + release を意味しています。これだけで memory_order_acq_rel な Atomic 操作になります。

; armv8.0a
loop:
    ldaxr   w9, [x8]
    add     w1, w9, #10
    stlxr   w9, w1, [x8]
    cbnz    w9, loop

ARMv8.1 (AArch64) では命令が拡張されており x64 同様 1命令で済むようになっています。ldaddal の最後の al が acq_rel を意味しており、他に relaxed, acquire, release があるので 4通りです。さらにサイズも 8, 16, 32, 64bit から選べるので ldadd だけでも 16 種類あることになります。

; armv8.1a
    ldaddal w23, w8, [x22]

ARMv8.1 は add 以外の atomic 演算にも対応しています。

例えば x64 の場合 xadd 以外の演算命令がないので fetch_xor( 7 ) は load + xor + CAS に展開されています。

; x64
loop:
    movl  8(%rsp), %ecx
    movl  %ecx, %edx
    xorl  $7, %edx
    movl  %ecx, %eax
    lock  cmpxchgl  %edx, 8(%rsp)
    jne   loop

ARMv8.1 ではこれも 1命令です。他にも and, or 相当の ldclr/ldset があります。

; armv8.1a
    ldeoral w8, w1, [x19]


● compare_exchange (CAS) の weak/strong の違い

ARMv7/ARMv8.0 では compare_exchange_weak() と compare_exchange_strong() で違いがあります。strong は LL/SC の失敗時に再実行しますが weak はそのまま抜けます。SpinLock など CAS の戻り値によって繰り返し呼び出す用途では、判定が二度手間になるため weak で十分なことになります。

; armv8.0a  cas-weak (0 -> 3)
    ldaxr  w2, [x19]
    cbnz   w2, lbb18
    orr    w8, wzr, #0x3
    stlxr  w9, w8, [x19]
    b      lbb19
lbb18:
    clrex
lbb19:

strong では再実行あり。

; armv8.0a  cas-strong (3 -> 0)
loop:
    ldaxr  r2, [x19]
    cmp    w2, #3
    b.ne   lbb24
    stlxr  w8, wzr, [x19]
    cbnz   w8, loop
    orr    w1, wzr, #0x1
    b      lbb25
lbb24:
    clrex
lbb25:

x64 と ARMv8.1A はそれぞれ weak/strong の違いがなく 1命令です。

; x64
    lock  cmpxchgl  %ebx, 8(%rsp)

; armv8.1a
    casal    w2, w3, [x22]

casal は Compare and Swap (CAS) + acq_rel。



● memory_order の違い

load/store それぞれの memory_order 指定による違いは下記の通り。まずは load の場合。

; armv7a

; (relaxed)
    ldr    r0, [r4]

; (acquire/consume/seq_cst)
    ldr    r0, [r4]
    dmb    ish

ARMv8.1 の違いは特になく 8.0 と同じでした。

; armv8.0a/armv8.1a

; (relaxed)
    ldr    w1, [x19]

; (acquire/consume/seq_cst)
    ldar   w1, [x19]

store の場合。

; armv7a

; (relaxed)
    str    r5, [r4]

; (release)
    dmb    ish
    str    r5, [r4]

; (seq_cst)
    dmb    ish
    str    r5, [r4]
    dmb    ish


; armv8.0a/armv8.1a

; (relaxed)
    str    w20, [x19]

; (release/seq_cst)
    stlr   w20, [x19]

x64 では store( seq_cst ) に xchg が使われている以外は全部 mov です。ARM では厳密に Memory Barrier が挿入されています。

Snapdragon 845 向けに ARMv8.2 バイナリを作ると思ったよりも生成コードに違いがあることがわかりました。iOS では従来の arm64 に加えて arm64e が追加されており、ARM v8.x 拡張命令に対応した新しいバイナリを区別しています。Android では特に区別がないですが、fp16 演算を使った最適化を行う場合は ARMv7 + NEON のときと同じように binary を分けてロードする必要があるかもしれません。

実際の出力などより詳しくは下記のページにまとめています。

CPU Atomic / Memory Barrier


関連ページ
CPU Atomic / Memory Barrier

関連エントリ
Snapdragon 845 ARMv8.2A 半精度 fp16 演算命令を使ってみる / Deep Learning 命令
スレッド同期命令の比較 C++11 とコンパイラ


UserLAnd を使うと Android 上に簡単に Linux 環境を構築することができます。開発環境としてはすでに termux がありますが、UserLAnd の場合動作可能なソフトウエアが多いのが魅力です。日本語入力環境も構築できるので、termux を補う意味でも併用がおすすめ。

前回までの記事はこちら

結構こまめに更新されているので、修正された部分などいくつか。


●画面サイズの自動認識

以前は VNC を選択すると 1024x768 の固定サイズになっていました。大半のスマートフォンはアスペクト比が異なるので、画面いっぱいに広げるには自分で設定ファイルに解像度を書き込んでおく必要があります。

新しい UserLAnd では自動的にスマートフォンの画面に合わせたサイズが選ばれるようになっています。設定をいじらなくても全画面です。

ただしハイエンド機種はピクセル密度が高いので、そのままだと文字が読めないほどウィンドウが小さくなってしまう場合があります。(5.5inch で 2560x1440 dot など) 必要に応じて .vncrc を修正してください。


●VNC 画面サイズの設定方法

従来は Linux Distribution 毎に設定ファイルが異なっていました。例えば Debian は ~/.vncrc で行い、Ubuntu は ~/.vnc/tightvncserver.conf、Arch Linux は ~/.vnc/config とばらばらです。

新しい UserLAnd では ~/.vncrc に統一されています。proot 外のスクリプトによって VNC Server 起動時に $HOME/.vncrc を読み取って起動時のコマンドオプションに指定しているようです。Debian は問題ありませんが、Ubuntu や Arch の場合以前の設定が無効化されているので注意。


●Desktop 環境のインストール

UserLAnd のアプリケーションメニューに Desktop が追加されたので、コマンドを打たなくてもデスクトップ環境を install できるようになっています。Lxde, Xfce の選択ができます。ただしインストールされるのは Debian になります。

UserLAnd Xfce

以前は VNC を選択してもデフォルトの twm + xterm のみで、Desktop 環境は自分でインストールする必要がありました。


●その他細かいこと

Alpine Linux が追加されているので Alpine, Arch, Debian, Kali, Ubuntu の 5種類から選択できるようになっています。

Filesystem のバックアップが可能になっています。Filesystem タブから個別に Export, Import できるようです。



関連エントリ
UserLAnd : Android 9.0 で Ctrl + SPACE を使えるようにする
Android Termux で日本語入力を行う / UserLAnd との併用
Android 9.0 と Bluetooth Keyboard による日本語入力
Android で動く Linux 環境 UserLAnd が XServer XSDL に対応
Oculus Go を文章書き&開発マシンにする
UserLAnd とブラウザ
Android 上の開発環境と UserLAnd
OS の中の Linux (WSL/Chrome OS/Android UserLAnd)
ARM CPU 上の開発環境とコンパイル時間の比較 (2) Pixel 3/UserLAnd


以前こちらで書いたように Android 9.0 Pie 以降は、外付けキーボード利用時に Control + SPACE のキー入力ができなくなっています。「キーボードレイアウトの切り替え」操作に割り当てられているためです。

ソフトウエアによっては Ctrl + SPACE を使いたい場合も多いので、無理やり使えるようにしてみました。

Ctrl + [SPACE] を乗っ取っているのは Android なので、Android 側で Ctrl を利用頻度の低いキーと交換してしまいます。例えば [F12] など。ただし入れ替えは UserLAnd + Linux (xmodmap) で識別可能なキーに限ります。本当は Caps が使えればよかったのですが Linux 側でうまく識別できませんでした。

もちろん Android 側では Ctrl キーが [F12] に置き換わってしまうため、ハードウエアキーボードで Ctrl を使った操作が困難になります。また xmodmap を使ったキー入れ替えは VNC/XSDL のみ有効で UserLAnd の SSH では使えません。


Step 1 : Android 側の入れ替え (kcm)

 [Ctrl] ←→ [F12]

・Android 側の「キーボードレイアウト切り替え操作」 は [F12]+[SPACE] になります。

Step 2 : UserLAnd Linux 側の入れ替え (xmodmap)

 [F12] ←→ [Ctrl]

・[F12] に偽装した本来の [Ctrl] キーを Ctrl として使えるようになります。



● (1) kcm キーレイアウト作成

Android 側でキー入れ替えを行うには kcm ファイルを作成し、新しいキーボードレイアウトを登録します。今回は下記 nakajit さんの code を利用させていただきました。

GitHub: nakajit/InputDevices4J

InputDevices4J/res/raw/keyboard_layout_japanese_ime_cc_ek.kcm を下記のように書き換えました。(Caps ←→ Ctrl, ESC ←→ 半全 が不要な場合は他のファイルを使用してください)

~
map key 58  CTRL_LEFT           # CAPS_LOCK
~

↓ 該当部分を下記のように修正

~
map key 58  F12                 # CAPS_LOCK
map key 88  CTRL_LEFT           # F12
~


● (2) 書き換えたプロジェクトを apk にビルドしてインストールします


● (3) 設定からレイアウトを選択

 設定→システム→言語と入力→物理キーボード→キーボードレイアウトの設定

keyboard_layout_japanese_ime_cc_ek.kcm の場合は「日本語 106/109 (IME用, C-C, E-H/Z)」を選びます。

選択すると Caps キーが [F12] に置き換わるので注意。


● (4) xmodmap での設定

UserLAnd から VNC を起動して xmodmap ファイルを作ります。

remove Control = Control_L
keysym Control_L = F12
keysym F12 = Control_L
add Control = Control_L

↑この内容を仮に .Xmodmap-F12 で保存したら

$ xmodmap .Xmodmap-F12

を実行します。


これで Android 9.0 でも UserLAnd (X11) 上で [Ctrl]+[SPACE] が使えるようになりました。

同じように、[半角/全角] キーや [変換] キーなども [F11], [F10] とか割り当ててしまえばおそらく UserLAnd 上で使用できるようになると思われます。


関連エントリ
Android Termux で日本語入力を行う / UserLAnd との併用
Android 9.0 と Bluetooth Keyboard による日本語入力
Android で動く Linux 環境 UserLAnd が XServer XSDL に対応
Oculus Go を文章書き&開発マシンにする
UserLAnd とブラウザ
Android 上の開発環境と UserLAnd
OS の中の Linux (WSL/Chrome OS/Android UserLAnd)
ARM CPU 上の開発環境とコンパイル時間の比較 (2) Pixel 3/UserLAnd


Termux や SSH Terminal では外付けの Bluetooth Keyboard を使うと快適なのですが、Android 上の日本語入力はなかなか思い通りにならないことがあります。OS Version や端末、キーボードソフトウエアによってキー操作や挙動が異なっています。また Terminal 上で On/Off できるかどうかもソフトによって差があります。

例えば Android 9.0 Pie では下記の操作が有効になっています。

(1) [Win] + [SPACE] キーボードの切り替え (Gboard←→ATOK 等)
(2) [SHIFT] + [SPACE] 他 Gboard/Google 日本語入力の 日本語 On/Off
(3) [Ctrl] + [SPACE] 物理キーボードレイアウトの切り替え (QWERTY←→Dvorak等)


(1) キーボード切り替え (Win + SPACE)

複数のキーボードソフトを入れているとそれらを順番に切り替えます。例えば Google 日本語入力 と ATOK を両方有効にしているなら [Win] + [SPACE] で交互に切り替わります。


(2) 日本語入力切り替え

日本語入力切り替え操作はキーボードソフトウエアによって異なります。

ハードウエアキーボード利用時の日本語入力切り替えキーまとめ

Keyboard Software [半全]以外の On/Off キー [半全] ALT+[半全] Term
Gboard (+日本語) [SHIFT] + [SPACE] Y - -
Google 日本語入力 [SHIFT] + [SPACE] Y - -
ATOK for Android [ALT] + [SPACE] / [変換] Y Y Y
FSKAREN for Android 無し Y Y -
Wnn Keyboard Lab [SHIFT] + [SPACE] Y Y -

[半全] = [半角/全角] キーで切り替えられるかどうか
ALT+[半全] = [ALT] + [半角/全角] キーで切り替えられるかどうか
Term = Termux/ConnectBot 上で日本語 On/Off できるかどうか (変換中文字表示なし)

ATOK は複数の操作ができますがどれも同じ機能です。ATOK は [変換] キーが使えます。FSKAREN / Wnn は英数時に直接入力と変換入力切り替えの使い分けができます。ただし FSKAREN と Wnn は操作が逆でした。

Keyboard Software On/Off (直接入力) 英数/日本語 (変換入力)
Gboard (+日本語) - [SHIFT]+[SPACE] / [半全]
Google 日本語入力 - [SHIFT]+[SPACE] / [半全]
ATOK for Android - [ALT]+[SPACE] / [半全] / [ALT]+[半全] / [変換]
FSKAREN for Android [ALT]+[半全] [半全]
Wnn Keyboard Lab [半全] [SHIFT]+[SPACE] / [ALT]+[半全]


(3) 物理キーボードレイアウト切り替え (Ctrl + SPACE)

これは Android 9.0 から追加された操作で Android 8.1 以前にはありません。以降は Essential Phone、Android 9.0 での画面です。

Bluetooth または USB Keyboard をつないだ状態で設定を開きます。「システム」→「言語と入力」→「物理キーボード」を開くとキーボードの名前が表示されているので選択

AndroidKeyboard

「キーボードレイアウトの選択」画面がでます。

AndroidKeyboard

右下の「キーボードレイアウトの選択」を選ぶと複数のレイアウトを選択できます。

AndroidKeyboard

複数のレイアウトにチェックをれて戻ると下記の通り。この画面でようやく Ctrl+スペース の操作が割り当てられていることがわかります。

AndroidKeyboard

おそらく QWERTY と Dvorak のように、キーボードレイアウト自体をいつでも切り替えられるように設けられた機能だと思われます。

ただし弊害があります。この機能が原因で Android 9.0 では Terminal アプリケーションで [Ctrl] + [SPACE] の操作ができなくなっているのだと思われます。例えば Termux や SSH Terminal 、UserLAnd や VNC 上で [Ctrl] + [SPACE] を使おうとしても、入力できずにレイアウトが切り替わってしまいます。

[Ctrl]+[SPACE] で日本語切り替えしたい場合や、Emacs のマーク操作で困ります。Android 8.1 以前は問題なく [Ctrl]+[SPACE] が使えました。


● Termux で日本語入力を行う

Termux 上で Android 上の日本語変換を使う場合は、切り替え操作が思うようにできないだけでなく変換途中の文字列が表示されない問題もあります。なので、いっそ Android 側の日本語入力機能を諦めてしまうのも一つの手です。

UserLAnd のおかげで Android 内に簡単に Linux Distribution をインストールできるようになりました。つまり UserLAnd を GUI&日本語入力対応の SSH Terminal として利用します。

Termux 上で予め sshd を立ち上げてから UserLAnd 上で ssh localhost -p 8022 で接続します。これで Termux 上で uim-mozc や fcitx-mozc を使った日本語入力↓ができます。

UserLAnd_Termux

ただし Android 9.0 の場合は Ctrl+SPACE が使えない問題は相変わらず残ります。

UserLAnd 使うなら、そもそも Termux は必要ないのではないかと思うかもしれませんが、詳しくは次回に続きます。
続き: Android Termux で日本語入力を行う / UserLAnd との併用


関連ページ
Android の上の開発環境: UserLAnd
Android の上の開発環境: Termux

関連エントリ
Android で動く Linux 環境 UserLAnd が XServer XSDL に対応
Oculus Go を文章書き&開発マシンにする
UserLAnd とブラウザ
Android 上の開発環境と UserLAnd
OS の中の Linux (WSL/Chrome OS/Android UserLAnd)
ARM CPU 上の開発環境とコンパイル時間の比較 (2) Pixel 3/UserLAnd


Snapdragon 835 (MSM8998) のデータを追加しました。コンパイル時間と VFP Benchmark の結果を載せています。ついでに Oculus Go でもコンパイル時間を調べてみました。(前回1) (前回2)

●コンパイル時間の比較 (Termux+clang)

Smartphone SoC RAM Thread Time 速度比
Pixel 3 Snapdragon 845 4GB 8/8 32 4.2x
Essential Phone Snapdragon 835 4GB 8/8 38 3.6x
Galaxy S6 Edge Exynos 7420 3GB 8/8 77 1.8x
ZenFone AR Snapdragon 821 8GB 4/4 111 1.2x
Nexus 5X Snapdragon 808 2GB 6/6 135 1.0x
Oculus Go Snapdragon 821 3GB 4/4 275 0.5x

・Time (秒) が小さい方が高速。


●浮動小数点演算能力ピーク値 (VFPBenchmark)

Smartphone SoC RAM Thread big/L GFLOPS
Pixel 3 Snapdragon 845 4GB 8/8 84/55 139.3
Essential Phone Snapdragon 835 4GB 8/8 75/59 134.5
Galaxy S6 Edge Exynos 7420 3GB 8/8 56/47 102.6
Nexus 5X Snapdragon 808 2GB 6/6 29/45 74.0
ZenFone AR Snapdragon 821 8GB 4/4 37/25 62.7

・GFLOPS が大きい方が高速。


演算ユニットの数が同じなので浮動小数点演算ピーク値はクロック数に比例した結果となっています。特に Total 値では 835 と 845 の差が少なくほぼ同じくらいの数値です。

それと比べるとコンパイル時間の方には若干差が付きました。CPU 自体も 2 命令 decode の Out-of-order から 3 命令 decode Out-of-order に増えていますので、Snapdragon 845 は big core のクロック差だけでなく IPC も向上しています。ベースとなった CPU core は ARM によると 20% 以上速いとのこと。UserLAnd + Termux を使っていても VNC 経由なのに十分満足できるもので、過去に使った Nexus 7 (2012) や Nexus 5 の Linux とは別物です。

Oculus Go で動く UserLAnd や Termux はどこでも大画面で作業場が作れるので魅力的なのですが、ビルドは残念ながら低速です。同じ Snapdragon 821 の Zenfone AR と比べても 2.5 倍時間がかかりました。使用したのは Oculus TV + Termux です。VR 空間の描画にパフォーマンスが取られているのだと思われます。VR 描画は両眼分必要で、また処理落ちは酔いにつながるため VR 描画が優先されます。


●スマートフォン以外のデバイスを含めたコンパイル時間の比較

他のデバイスとの比較表も更新しました。835 も十分速いです。ただし条件が一定ではないので参考程度にお願いします。特に Windows 10 PC は仮想環境を使っています。

Device SoC/CPU RAM Thread Time
Desktop W10+VMware Ryzen 7 1800X 16GB 16/8 24
Desktop W10+WSL Ryzen 7 1800X 32GB 16/8 26
Desktop W10+VMware Core i7-6700K 16GB 8/4 29
Pixel 3 Snapdragon 845 4GB 8/8 32
Desktop W10+VMware Core i7-4790K 8GB 8/4 35
Essential Phone Snapdragon 835 4GB 8/8 38
Desktop W10+VMware Core i7-4770 8GB 8/4 39
MacMini 2012 Core i7-3615QM 16GB 8/4 43
Galaxy S6 Edge Exynos 7420 3GB 8/8 77
Desktop Linux A10-7870K 8GB 4/2 82
Chromebook C101PA RK3399 4GB 6/6 87
MacBook Pro 2013 Core i5-3210M 8GB 4/2 97
Desktop Linux Celeron J1900 8GB 4/4 108
ZenFone AR Snapdragon 821 8GB 4/4 111
Nexus 5X Snapdragon 808 2GB 6/6 135
Tegra Note 7 Tegra 4 1GB 4/4 148
Note W10+WSL Atom x7-Z8700 4GB 4/4 200
Chromebook C720 Celeron 2955U 4GB 2/2 222
Nexus 9 Tegra K1 2GB 2/2 272
Nexus 7 2013 Snapdragon S4 Pro 2GB 4/4 275
Oculus Go Snapdragon 821 3GB 4/4 275
MeMO Pad 7 ME176C Atom Z3745 1GB 4/4 312

・Time (秒) が小さい方が高速。


関連ページ
VFP Benchmark Log 計測結果まとめ

関連エントリ
Snapdragon 845 の浮動小数点演算速度
ARM CPU 上の開発環境とコンパイル時間の比較 (2) Pixel 3/UserLAnd
ARM CPU 上の開発環境とコンパイル時間の比較
AMD CPU Ryzen とコンパイル時間の比較 (2)
AMD CPU Ryzen とコンパイル時間の比較
ARM CPU の浮動小数点演算能力まとめ
HTC 10 Snapdragon 820 Kyro の浮動小数点演算能力
iPhone SE, Apple A9 の浮動小数点演算速度
Raspberry Pi 3 の速度比較, Cortex-A53 の速度
ARM Cortex-A53 の浮動小数点演算速度とコンパイル時間の比較
2955U vs N3150/J1900/Athlon5350 (コンパイル時間の比較)
iPod touch 6 の浮動小数点演算速度は Core 2 Duo ライン超え
Raspberry Pi 2 で速くなったコンパイル時間の比較
iPad Air 2 (Apple A8X) の浮動小数点演算能力
BayTrail vs Kabini (Celeron J1900 vs Athlon 5350)
コンパイル時間の比較 BayTrail
Atom vs Core i7


| 次のページ(日付が古い方向)>>