月別アーカイブ: 2024年7月

Google Tensor G3 の浮動小数点演算性能と SVE

SVE/SVE2 は ARM の新しい SIMD 命令です。特徴は、従来よりも長いサイズのベクタを扱えるようになったことです。AVX512 のマスクレジスタと同じように Predicate Register を持っており、任意長のベクタとしても扱うことができます。

AVX512 と違って CPU 側の実際のレジスタサイズは任意です。128bit の倍数なら何でもよく、最大で 2048bit になります。レジスタ長に応じてループ回数やマスク値を設定する命令が存在しており、CPU 毎の実装の違いを吸収することができます。

Tensor G3 は ARMv9 の CPU Coretex-X3/A715/A510 を搭載しているため SVE/SVE2 命令に対応しています。Cortex-X3/A715/A510 のレジスタサイズは 128bit でした。これは NEON 命令と同じなので、浮動小数点演算のピーク性能自体はどちらを使っても変わらないと思われます。

vfpbench に SVE 命令を追加したので Pixel 8 で試してみました。

Cortex-A510 SingleT SP                          FLOPS                      IPC
NEON fmul.4s (32bit x4) n12       :    0.454    13519.8     3379.9  (  4.0 2.0)
NEON fadd.4s (32bit x4) n12       :    0.453    13543.1     3385.8  (  4.0 2.0)
NEON fmla.4s (32bit x4) n12       :    0.453    27055.6     3382.0  (  8.0 2.0)
SVE fmul.s (32bit xN) n12         :    0.453    13529.6     3382.4  (  4.0 2.0)
SVE fadd.s (32bit xN) n12         :    0.454    13523.3     3380.8  (  4.0 2.0)
SVE fmla.s (32bit xN) n12         :    0.453    27080.5     3385.1  (  8.0 2.0)


Cortex-A715 SingleT SP                          FLOPS                      IPC
NEON fmul.4s (32bit x4) n12       :    0.452    18864.7     4716.2  (  4.0 2.0)
NEON fadd.4s (32bit x4) n12       :    0.452    18868.5     4717.1  (  4.0 2.0)
NEON fmla.4s (32bit x4) n12       :    0.452    37731.6     4716.5  (  8.0 2.0)
SVE fmul.s (32bit xN) n12         :    0.451    18897.2     4724.3  (  4.0 2.0)
SVE fadd.s (32bit xN) n12         :    0.452    18847.1     4711.8  (  4.0 2.0)
SVE fmla.s (32bit xN) n12         :    0.452    37717.2     4714.6  (  8.0 2.0)


Cortex-X3 SingleT SP                            FLOPS                      IPC
NEON fmul.4s (32bit x4) n12       :    0.676    46546.0    11636.5  (  4.0 4.0)
NEON fadd.4s (32bit x4) n12       :    0.678    46425.0    11606.2  (  4.0 4.0)
NEON fmla.4s (32bit x4) n12       :    0.902    69792.8     8724.1  (  8.0 3.0)
SVE fmul.s (32bit xN) n12         :    0.675    46594.6    11648.6  (  4.0 4.0)
SVE fadd.s (32bit xN) n12         :    0.679    46365.2    11591.3  (  4.0 4.0)
SVE fmla.s (32bit xN) n12         :    0.901    69842.9     8730.4  (  8.0 3.0)

右端の IPC を見るとわかりやすいでしょう。シングルスレッド単精度による結果の比較ですが、やはり 128bit 演算になるため NEON、SVE どちらも結果に違いはありませんでした。もちろん 256bit や 512bit 対応 CPU では結果が異なりますし、マスクレジスタを利用できるという大きなメリットもあります。

SVE とは関係ないですが、少々気になるのは Cortex-A510 の結果です。128bit 命令の IPC が 2 となっており、これは Tensor G2 の Cortex-A55 と比べると 2倍の数値となります。この結果だけ見るとクロックあたりの浮動小数点演算演算能力が上位 CPU と同じ水準まで強化されているように見えます。

そのため A55 世代と比べると全体のピーク FLOPS 値が大きく伸びているはずですが、結果を見ると思ったほど上がっていません。以下の表は A55 との比較です。シングルスレッド性能は 2倍になっているのにマルチスレッド性能はあまり変わっていないことがわかります。

SoCCPU CoreClockcore数Single-T SPMULTI-T SP
Tensor G3Cortex-A5101.70 GHz427.1 GFLOPS61.3 GFLOPS
Tensor G2Cortex-A551.80 GHz414.0 GFLOPS54.7 GFLOPS
↑ 浮動小数点演算命令単精度のピーク値、FLOPS の値が大きい方が高速

その要因はマルチスレッド時の各命令の詳細をみると明らかです。マルチスレッド実行時は Cortex-A510 の演算能力 (IPC) が半減しています。

Cortex-A510 SingleT SP                          FLOPS                      IPC
NEON fmul.4s (32bit x4) n12       :    0.454    13519.8     3379.9  (  4.0 2.0)
NEON fadd.4s (32bit x4) n12       :    0.453    13543.1     3385.8  (  4.0 2.0)
NEON fmla.4s (32bit x4) n12       :    0.453    27055.6     3382.0  (  8.0 2.0)
SVE fmul.s (32bit xN) n12         :    0.453    13529.6     3382.4  (  4.0 2.0)
SVE fadd.s (32bit xN) n12         :    0.454    13523.3     3380.8  (  4.0 2.0)
SVE fmla.s (32bit xN) n12         :    0.453    27080.5     3385.1  (  8.0 2.0)

Cortex-A510 MultiT SP                           FLOPS                      IPC
NEON fmul.4s (32bit x4) n12       :    0.885    27730.1     1733.1  ( 16.0 1.0)
NEON fadd.4s (32bit x4) n12       :    0.907    27041.8     1690.1  ( 16.0 1.0)
NEON fmla.4s (32bit x4) n12       :    0.906    54190.8     1693.5  ( 32.0 1.0)
SVE fmul.s (32bit xN) n12         :    0.909    26991.1     1686.9  ( 16.0 1.0)
SVE fadd.s (32bit xN) n12         :    0.904    27150.5     1696.9  ( 16.0 1.0)
SVE fmla.s (32bit xN) n12         :    0.801    61290.4     1915.3  ( 32.0 1.1)

AMD Bulldozer 系のように演算ユニットが複数のコアで共有されているか、もしくはマルチスレッド高負荷時のクロック制限の可能性などを考えましたが、結果は前者でした。Arm CortexA510 Core Software Optimization Guide によると A510 の浮動小数点演算ユニットはどうやら 2 core で共有されているようです。

よって Cortex-A510 では 64bit 命令の場合は core あたり 2命令ですが、128bit 命令はシングルスレッドでピーク 2命令、マルチスレッドでは競合した場合 1命令までに制限されます。

以下の表は他の CPU との比較です。

SOCPRIMEBIGLITTLE合計CORE数S-SPM-SP
Tensor G3X3 2.91GHz x1A715 2.37GHz x4A510 1.70GHz x4969.8281.9
Tensor G2X1 2.85GHz x2A78 2.35GHz x2A55 1.80GHz x4848.8227.5
Kirin 980A76 2.60GHz x2A76 1.92GHz x2A55 1.80GHz x4841.5186.7
Helio G99A76 2.20GHz x2A55 2.00GHz x6835.2163.8
↑ 浮動小数点演算命令単精度のピーク値、S-SP/M-SP の単位は GFLOPS。FLOPS の値が大きい方が高速

Cortex-X3 は 128bit で 4命令実行できる点は X1 と変わりませんが、fma のスループットが向上しておりそれが S-SP の結果に反映されています。X1 では fma の IPC が 2 でしたが X3 では 3 命令同時に実行できています。

Cortex-X3/A715/A510 では他にも i8mm や bf16 など ML 系の命令が増えていますので、そちらも後ほど調べてみたいと思います。

関連エントリ

UE5 Intel N100 1台だけでも分散ビルドの効果はあるかどうか

Unreal Engine を使った開発ではビルドに時間がかかります。特にソースコード版のエンジンを使うとエンジン全体のコンパイルも同時に行われる場合があり、1時間近く待たされることも少なくありません。

時間がかかるコンパイルを複数台の PC を使って高速化する仕組みが分散ビルドです。UE5 5.4 ではエンジンの機能として分散ビルドツール UnrealBuildAccelerator (UBA) が付属するようになりました。

前回の記事で UE5 の分散ビルド UBA を使うとビルドを大幅に高速化できることがわかりました。ですが家に PC が何台もあるケースはそんなに多くないと思われます。そこで非力な PC 1台との組み合わせでも、分散ビルドを行う意味があるのかどうか調べてみました。

Intel N100 (Alder Lake-N) の場合

以下は開発用 PC に Intel N100 搭載 PC を組み合わせて分散ビルドを行った結果です。(Intel N100 の性能について詳しくはこちら)

CPUARCHCore数Thread数単独でのビルド時間分散ビルド利用時削減時間
Ryzen 5 3600Zen261291m 28s74m 46s-16分42秒
Core i7-13700RaptorLake162448m 00s44m 37s-3分23秒
↑UE5 5.4.2 の Win64 Development Editor の C++ コンパイル時間の比較

Ryzen 5 3600 単独でビルドを行うと 91分かかりますが、N100 との分散ビルドで約 17分短縮できることがわかりました。思ったよりも効果が出ています。

流石に性能が高い Core i7-13700 の場合は 3分少々しか変わりませんが、それでもきちんと速くなっています。

分散ビルドでは通信のオーバーヘッドがありますし、非力な PC の完了待ちで逆に遅くなる可能性も考えられます。ですがこの結果を見ると少ないながら速度が向上しているため、安心して分散化できそうです。なお HordeServer も同じ N100 PC 上で走らせています。

さらに、他の PC との組み合わせでもビルド時間を調べてみました。

他の PC との組み合わせの結果一覧

ビルドPC組み合わせた分散PC合計Core数合計Thread数ビルド時間削減時間
Ryzen 5 3600なし61291m 28s
Ryzen 5 3600Core i5-1030NG7102077m 37s-13分51秒
Ryzen 5 3600Intel N100101674m 46s-16分42秒
Ryzen 5 3600Core i7-4790K102061m 40s-29分48秒
Ryzen 5 3600Ryzen 5 2600122457m 24s-34分04秒
Ryzen 5 3600Ryzen 5 5560U122456m 55s-34分33秒
Ryzen 5 3600Core i7-13700223634m 17s-57分11秒
Core i7-13700なし162448m 00s
Core i7-13700Inte N100202844m 37s-3分23秒
Core i7-13700Core i7-1030NG7203244m 20s-3分40秒
Core i7-13700Core i7-4790K203239m 29s-8分31秒
Core i7-13700Ryzen 5 2600223637m 38s-10分22秒
Core i7-13700Ryzen 5 5560U223637m 26s-10分34秒
Core i7-13700Ryzen 5 3600223633m 32s-14分28秒
↑UE5 5.4.2 の Win64 Development Editor の C++ コンパイル時間の比較

結果から、分散ビルドに使えるマシンが 1台だけ (合計 2台) でもエンジンのビルドではそれなりに効果があることがわかります。UE5 の開発で頻繁にエンジンビルドが走る場合は、空いている PC を使って UBA を入れておくと良さそうです。詳しい導入手順については前回の解説記事をご覧ください。

開発に使っている PC の性能が低い方が恩恵は多いのですが、Ryzen 5 3600 と Core i7-13700 の組み合わせ結果を見ると、どちらでビルドを開始してもビルド時間がほぼ変わりませんでした。このケースではかなり効率よく分散できていることがわかります。

台数でカバーする

使える CPU コア数が多い方がビルドは速くなっています。以下の表は、性能が高い PC 1台使った場合と、非力&古い PC を多数組み合わせた場合を比較したものです。

ビルドPC組み合わせた分散PC合計CORE数合計THread数ビルド時間削減時間
Ryzen 5 3600Core i7-13700223634m 17s-57分11秒
Ryzen 5 3600N100+1030NG7+2600+4790K+6700K285236m 23s-55分05秒
↑UE5 5.4.2 の Win64 Development Editor の C++ コンパイル時間の比較

使用した PC は Intel N100、Core i5-1030NG7、Ryzen 5 2600、Core i7-4790K、Core i7-6700K の 5台です。コア数が少ないものだけ選んでいますが、非力な PC でも数を集めることで、おおよそ Core i7-13700 1台分くらいの性能を出すことができていることがわかります。

速い PC の中に N100 を入れた場合

今度は速い PC 複数台でかなり高速に分散ビルドできている状態で、N100 や Core i5-1030NG7 など性能が低い PC を追加してみます。ビルドに使った PC は Core i7-13700 です。

組み合わせた分散PC台数合計CORE合計THREADビルド時間
13700+3950X+4750G+3600+2600+5560U+4790K76211614m 37s
13700+3950X+4750G+3600+2600+5560U+4790K+N10086612014m 07s
13700+3950X+4750G+3600+2600+5560U+4790K+1030NG786612414m 26s
13700+3950X+4750G+3600+2600+5560U+4790K+1030NG7+N10097012813m 42s
↑UE5 5.4.2 の Win64 Development Editor の C++ コンパイル時間の比較

遅い PC が足を引っ張ることもなく安定して動作しました。むしろわずかながら速度が向上しているため、性能が低くてもとりあえず Agent を追加して増やしていく方針で大丈夫そうです。

使った PC のスペック一覧その他

以下はテストに使った PC のスペック詳細になります。Ryzen 5 3600, Core i7-6700K など一部電力制限をかけた状態となっていますのでご了承ください。すべて 有線 LAN を使っています。

CPUTDPARCHCORE数THREAD数RAM容量SSD
Ryzen 5 360045WZen261264GBNVMe3
Core i7-1370065WRaptorLake162464GBNVMe4
Intel N10020WAlderLake-N4416GBNVMe3
Core i5-1030NG710WIceLake4816GBNVMe3
Core i7-4790K88WHaswell4816GBSATA
Core i7-6700K60WSkyLake4832GBSATA
Ryzen 5 260065WZen1+61232GBNVMe3
Ryzen 5 5560U25WZen361232GBNVMe3
Ryzen 7 4750G65WZen281632GBNVMe3
Ryzen9 3950X105WZen2163232GBNVMe3

UnrealBuildAccelerator は PC 性能によらず分散の効果がわかりやすいので、導入のハードルがかなり下がったのではないかと思います。今回は C++ のコンパイルのみ試しましたが、ビルド時間を短縮できますので UE5 での開発効率が大きく向上しそうです。

関連エントリ

UE5 のビルドを速くする、分散ビルド UnrealBuildAccelerator を使う

UE5 5.4 には UnrealBuildAccelerator (以下 UBA) という分散ビルドツールが付属しています。家に複数台の PC がある場合は、それぞれインストールしておくとことでビルド時間を大幅に短縮することができます。

実際に空いている PC を使って UE5 のビルドがどれくらい速くなるの比較してみました。以下の表は UE5 5.4.2 Win64 Development Editor のエンジンリビルド時間の比較です

CPUARCHCoRE数THREAD数単独ビルド時間分散ビルド利用時ビルド速度
Core i7-13700RaptorLake162448m 00s15m 21s3.1 倍
Ryzen 5 3600Zen261291m 28s16m 28s5.6 倍
UE5 ビルド時間の比較、ビルド時間が短い方が高速

Core i7-13700 では 48分かかっていたビルドが分散ビルド利用時でわずか 15分。単独でビルドしていた場合の 1/3 の時間で完了しています。

コア数が少ない Ryzen 5 3600 の場合はさらに効果が大きく、ビルド速度は 5.6倍にもなります。91分から 16分まで短縮できており、スタンドアロンの場合は Core i7-13700 の倍の時間がかかっていたものが、分散ビルドを使うとほぼ同じ時間で完了しました。

今回分散ビルドで使用した PC は以下のとおりです。

CPUARCHCORE数THREAD数RAM容量
Ryzen 5 2600Zen1+61232 GB
Ryzen 5 3600Zen261264 GB
Ryzen 5 5560UZen361232 GB
Ryzen 7 4750GZen281632 GB
Ryzen 9 3950XZen2163232 GB
Core i7-13700RaptorLake162464 GB
合計58108
ビルドに使用したヘルパー (Agent) PC 一覧

全部で PC 6台、合計 58コア 108スレッド使用しています。

Core i7-13700 でビルドした場合は他の 5台がビルド用のヘルパー (Agent) になります。本体 16コア 24スレッドで、加えて外部の PC が Agent として 42コア 84スレッド分追加される形になります。同じように Ryzen 5 3600 の場合は本体 6コア 12スレッドに対して外部の PC が 52コア 96スレッドです。

非常に効果が大きかったので、PC が複数台ある場合は UBA を使うことでビルド時間をだいぶ短縮できそうです。

以下分散ビルド UBA のインストール方法の詳細です。

インストール手順

インストールにあたってこちらのページを参考にさせていただきました。UBA について詳しくはこちらのページも参照してください。

(1) HordeServer インストール

どれか 1台の PC に HordeServer をインストールします。この手順は GitHub のソースコード版エンジン UE5 5.4 のものです。

  1. UnrealHordeServer.msi を実行してインストールします
    • GitHub 版のエンジンをビルドしている場合は Engine/Extras/Horde/UnrealHordeServer.msi にあります。
    • GitHub からダウンロード直後は Extras フォルダがないので、先に Setup.bat を実行しておく必要があります。
  2. このマシンに Port 13340 でアクセスできるようにしておきます
    • Firewall で制限がかかっている場合は、TCP Port 13340 でアクセスできるように設定しておいてください

(2) HordeAgent のインストール

ビルドに使いたい PC それぞれに Agent をインストールします。HordeServer と同じマシンにインストールしても構いません。

  1. ブラウザで HordeServer をインストルした PC にアクセスします
    • 「 http://サーバーPCのIPアドレス:13340/tools 」を開きます
  2. ダウンロードページが開くので「Horde Agent (Windows Installer) 」をダウンロードします
  3. ダウンロードした UnrealHordeAgent.msi を実行してインストールします
    • 「Horde Server URL:」には「 http://サーバーPCのIPアドレス:13340」を入力します
      • 注意: サーバーが自分自身の場合でも絶対に「localhost」や「127.0.0.1」を使わないでください。ここで接続に使用したアドレスが他の PC に配布されるので、localhost だとこの Agent にアクセスできなくなります。
    • 「Sandbox directory: 」はキャッシュとして使うフォルダを指定します
      • 空き容量の多い SSD ドライブをおすすめします。問題なければそのままでも構いません。
  4. インストールが終わると、ブラウザで自動的に「Agent Enrollment」のページが開きます
    • もし開かない場合は、タスクトレイの「U」アイコン (Unreal Engine のロゴ) 右クリックから「Enroll with Server…」を選択してください
  5. しばらくすると Agent Enrollment のページに PC 名が表示されるので、選択して右上の「Enroll Agents」をクリックします
    • PC が表示されるまで時間がかかる場合があります。数分待ってみてください。
  6. 登録が終わったら、「http://サーバーPCのIPアドレス:13340/agents」を開いて PC が表示されていることを確認してください
  7. タスクトレイに UnrealEngine ロゴのアイコン (UnrealHordeAgent) が登録されているので、右クリックして Status を「When Idle」に変更します
    • Status → When Idle
  8. Agent PC に Port 7000~7010 でアクセスできるようにしておきます
    • Firewall の設定で TCP Port 7000~7010 で受信できるようにしておきます

同じ手順で各 PC にそれぞれ HordeAgent をインストールしておきます。今回のテストでは 6台の PC 全てに Agent をインストールしています。

なお VisualStudio などビルド環境のセットアップは不要です。

(3) ビルドするための設定

ビルドを行う側の PC にもさらに追加の設定が必要です。

  1. BuildConfiguration.xml を作成します
    • 特定のエンジンだけで使用する場合は、エンジンフォルダ内の Engine/Saved/UnrealBuildTool/BuildConfiguration.xml に保存します
    • もし全部のエンジンで同じ設定を使いたい場合は、自分のドキュメントフォルダの中に 「ドキュメント\Unreal Engine\UnrealBuildTool\BuildConfiguration.xml」のように入れてください
  2. BuildConfiguration.xml の内容は以下のとおりです
    • xml 内の「サーバーPCのIPアドレス」の部分は置き換えてください。
    • すでに BuildConfiguration.xml が存在する場合は内容を追加してください。
<?xml version='1.0' encoding='utf-8'?>
<Configuration xmlns="https://www.unrealengine.com/BuildConfiguration">
    <BuildConfiguration>
        <bAllowFASTBuild>false</bAllowFASTBuild>
        <bAllowUBAExecutor>true</bAllowUBAExecutor>
    </BuildConfiguration>
    <Horde>
        <Server>http://サーバーPCのIPアドレス:13340</Server>
        <WindowsPool>Win-UE5</WindowsPool>
    </Horde>
    <UnrealBuildAccelerator>
        <bLaunchVisualizer>false</bLaunchVisualizer>
        <bForceBuildAllRemote>false</bForceBuildAllRemote>
    </UnrealBuildAccelerator>
</Configuration>

これで完了です。この設定をした PC 上で UE5 の C++ ビルドを行うと分散ビルドが行われます。

ビルドを行う場合の注意点

ステータス切り替えについて

HordeAgent には PC の Idle 状態かどうか判定して Status を動的に切り替える機能があります。

ですが負荷の高い作業やゲームのテストプレイ、負荷の調査などを行う場合は、意図しないビルドタスクが割り当てられてしまわないように予め手動でステータスを切り替えておくことをおすすめします。

  1. タスクトレイの「U」(UnrealEngine ロゴ)アイコン右クリック → Status
  2. 普段は「 When Idle 」にしておく
  3. テストプレイ前に「 Disabled 」に切り替え、終わったら「When Idle」に戻す

Horde Agent の設定変更

サーバーの URL やキャッシュフォルダなど、インストール時に入力したパラメータをあとから UI 上で変更する方法が見つかりませんでした。変更したい場合は、もう一度インストーラーを実行し直すのが確実なようです。