Windows 10 を使って Intel CPU でゲーム開発をしてはいけない理由

近年の Intel CPU はスマートフォンや Apple と同じような非対称な CPU Core を採用しています。高性能コアと呼ばれる P-Core と、高効率(低消費電力)コアである E-Core の組み合わせです。この非対称な構造は Core i の第 12 世代 (Alder Lake) から用いられており、Core i9 で比較すると以下のようになります。

CPU P-CoreE-Core合計コア数合計スレッド数
2021年Core i9-12900KAlderLake881624
2022年Core i9-13900KRaptorLake8162432
2023年Core i9-14900KRaptorLake Refresh8162432

P-Core はシングルスレッド性能が高く HT に対応しているものの消費電力が高く強力な冷却が必要になります。E-Core はピーク性能が低い代わりにコンパクトでより多くの Core を搭載できます。

Windows 10 が問題なのは、OS のスケジューラーがこの非対称な CPU コアの性能を引き出すことができずに著しく性能が落ちてしまう場合があるからです。

実際に Core i7-13700 を使用して Windwos 10 で UnrealEngine 5 のビルド時間を測定してみます。Core i7-13700 は Core i9-12900K 同様 8P + 8E の 16コア、24スレッドの CPU です。

CPUCoreCore数Thread数RAMSSDビルド時間比較
Core i7-13700RaptorLake162464GBNVMe 480分32秒↑遅い
Ryzen 5 3600Zen261232GBNVMe 377分46秒
Core i7-11700KRocketLake81632GBSATA68分46秒
Ryzen 9 3950XZen2163264GBNVMe 436分03秒↓速い
  • VisualStudio 2019、 UE5 5.1.1 の Development Editor をビルドしたときの時間の比較
  • ビルドにかかった時間が短い方が高速

ビルド時間で旧世代の CPU 「Core i7-11700K」に敵いません。Core i7-13700 は K 無し (65W) モデルということもありますが、同じ 65W でコア数が半分以下の CPU 「Ryzen 5 3600」にも負けていることがわかると思います。

Core i7-13700 のビルド速度が予想以上に遅くなっている原因はタスクマネージャーを見るとすぐに分かります。下はビルド中のタスクマネージャーをキャプチャしたものです。

↑ 本来 24スレッドあるはずなのに 1/3 の 8スレッドしか稼働していません。しかもこの 8 スレッドはちょうど E-Core の 8個分に相当します。

UnrealBuildTool (UBT) は 8 コアにしか割り当てられていないことを知らないため、本来の 24 スレッドと認識しています。ビルド中は 14 個ものコンパイラが起動しており、これがすべて E-Core 8個に押し込められてしまうわけです。

そこで、UEFI (BIOS) で E-Core を無効化して P-Core だけを使ってビルドしてみることにします。以下の表にその結果を載せています。E-Core を無効化するだけで 55分まで短縮されました。ビルドが 25分も早く終わります。

CPU コア数スレッド数RAMSSDビルド時間比較
Core i7-13700無変更162464GBNVMe 480分32秒↑遅い
Core i7-13700E-Core 無効化81664GBNVMe 455分43秒↓速い

原因と回避方法など

ビルド中のタスクマネージャーを見ると、コンパイラは「基本優先度」が「通常以下」(BelowNormal) の状態で走っていることがわかります。

Windows 10 のスケジューラはおそらく、優先度が「通常」(Normal) より低い場合に E-Core に割り当てる仕組みになっているものと思われます。実際に UE5 5.1.1 の UnrealBuildTool の設定値を書き換えて、プロセスの優先度を Normal まで上げるときちんと全部の CPU Core にタスクが割り振られるようになりました。

UnrealBuildTool だけでなく、同じ問題は他のツールでも発生します。例えばシェーダーのコンパイル (ShaderCompileWorker) も同様で、負荷が E-Core のみに集中することがわかっています。

この問題は Windows 11 を使うことで解決します。

WIndows 11 では低プライオリティのタスクが E-Core だけに割り当てられてしまうことが無く、優先度が「通常以下」(BelowNormal) の場合でもすべてのコアを使用してビルドを行います。ビルド速度の比較表に Windows 11 での結果を加えてみました。

CPU コア数スレッド数RAMSSDビルド時間比較
Core i7-13700Windows 10 無変更162464GBNVMe 480分32秒↑遅い
Core i7-13700Windows 10 E-Core 無効化81664GBNVMe 455分43秒
Core i7-13700Windows 11 無変更162464GBNVMe44分55秒↓速い

↑ Windows 11 にアップグレードするだけでビルド時間を 35分も短縮することができました。

タスクマネージャーでもきちんとすべてのコア、24スレッドが使われています。

なお、UE5 5.2 からは UnrealEngine 側でもこれらの対応が行われています。UnrealBuildTool (UBT) の ParallelExecutor 利用時は以下のように、CPU が非対称コアを搭載している場合、優先順位を「通常以下」(BelowNormal) ではなく「通常」(Normal) に設定するようになっています。

/// The priority to set for spawned processes.
/// Valid Settings: Idle, BelowNormal, Normal, AboveNormal, High
/// Default: BelowNormal or Normal for an Asymmetrical processor as BelowNormal can cause scheduling issues.
/// </summary>
[XmlConfigFile]
private static ProcessPriorityClass ProcessPriority = Utils.IsAsymmetricalProcessor() ? ProcessPriorityClass.Normal : ProcessPriorityClass.BelowNormal;

そのため Windows 10 でも UE5 5.2 以降はエンジンのビルド時間が短縮されるようになりました。ただしこれは根本的な解決ではなく、ツール個別の対応になるため注意が必要です。もし対応していないツールが存在する場合 (他の UBT Executor や分散ビルドなど) はやはりパフォーマンスが低下してしまう可能性があります。

Core i 12000 シリーズ (第12世代, AlderLake) が出たばかりの頃はまだ Windows 10 搭載 PC も出荷されていました。せっかく新しい PC に入れ替えたのに、ビルド時間がかえって遅くなってしまうなんてことがありました。

流石に今はもう無いと思いますが、Alder Lake 以降の Intel CPU 上でゲーム開発を行う場合は Windows 11 を使用することをお勧めします。

Ryzen Zen3 の vfpbench 結果

Zen4 と順序が逆になりましたが Zen3 の結果も手に入れることができました。モバイル向け APU、Ryzen 5 5560U です。

実行ユニットは Zen2 同様 256bit の乗算(積和) x2 + 加算 x2 の構成です。そのため単純な fma 換算ではピーク値が Zen2 と変わらない fma x2 となるのですが、Zen3 の場合少々結果が異なります。

AVX vmulps (32bit x8) n8          :    0.172    64245.3     8030.7  (  8.0 3.5)
AVX vaddps (32bit x8) n8          :    0.172    64267.0     8033.4  (  8.0 3.5)
AVX vmul+addps (32bit x8) n8      :    0.086   128217.7    16027.2  (  8.0 7.0)
FMA vfmaddps (32bit x8) n8        :    0.214   103087.1     6442.9  ( 16.0 2.8)
FMA vfmaddps (32bit x8) n12       :    0.275   120290.1     7518.1  ( 16.0 3.3)
FMA vfma+mlps (32bit x8) n12      :    0.258    96422.6     8035.2  ( 12.0 3.5)
FMA vfma+adps (32bit x8) n12      :    0.172   144552.0    12046.0  ( 12.0 5.2)
AVX vml+ad+adps (32bit x8) n9     :    0.244    50965.1     6370.6  (  8.0 2.8)

fma x2 よりも fma + add の方が値が高くなっており、fma x 2 に加えて add も十分なスループットで回っているように見えます。ピーク値も追加の add 命令の分だけ上昇しています。パイプライン構成自体は大きく変わらないものの、Zen2 より命令発行数と実行効率が向上し、演算性能が上がっている事がわかります。

Zen4 の場合はこれに加えてさらに AVX512 にも対応します。fma だけ見ると違いがないように見えるかもしれませんが、世代毎に演算能力は上がっています。

関連エントリ

Pixel 7a Google Tensor G2 の vfpbench の結果

Google の Pixel 7a は Pixel 7 や Fold と同じ Tensor G2 が搭載されています。Tensor G2 でも vfpbench を走らせてみました。

Tensor G2 には 3種類の CPU Core が搭載されています。

Cortex-A55x41.80 GHz
Cortex-A78x22.35 GHz
Cortex-X1x22.85 GHz

それぞれの結果を詳しく見ると、A55 はスカラーの add, mul, fma や 64bit 演算で 2命令走りますが 128bit 演算では 1命令です。よって 64bit 演算 x2 の構成であることがわかります。

A55
FPU fmul (32bit x1) n8            :    0.319     3389.7     3389.7  (  1.0 1.9)
FPU fadd (32bit x1) n8            :    0.334     3243.8     3243.8  (  1.0 1.8)
FPU fmadd (32bit x1) n8           :    0.319     6785.6     3392.8  (  2.0 1.9)
NEON fmul.4s (32bit x4) n12       :    0.924     7027.6     1756.9  (  4.0 1.0)
NEON fadd.4s (32bit x4) n12       :    0.928     6995.3     1748.8  (  4.0 1.0)
NEON fmla.4s (32bit x4) n12       :    0.924    14046.3     1755.8  (  8.0 1.0)

対して A78 はスカラーも 128bit 演算も変わらず 2命令で一定なので、128bit x2 になります。

A78
FPU fmul (32bit x1) n8            :    0.301     4676.9     4676.9  (  1.0 2.0)
FPU fadd (32bit x1) n8            :    0.301     4678.5     4678.5  (  1.0 2.0)
FPU fmadd (32bit x1) n8           :    0.301     9353.7     4676.9  (  2.0 2.0)
NEON fmul.4s (32bit x4) n12       :    0.452    18712.2     4678.1  (  4.0 2.0)
NEON fadd.4s (32bit x4) n12       :    0.452    18713.6     4678.4  (  4.0 2.0)
NEON fmla.4s (32bit x4) n12       :    0.452    37368.1     4671.0  (  8.0 2.0)

最上位の Cortex-X1 はスカラー・ベクター関係なく add/mul 演算で 4命令、fma で 2命令です。fma のピーク値だけ見るとあまり差がないように見えますが、128bit x4 と演算能力が大きく拡張されており高いスループットが期待できます。

X1
FPU fmul (32bit x1) n8            :    0.151    11337.4    11337.4  (  1.0 4.0)
FPU fadd (32bit x1) n8            :    0.150    11370.1    11370.1  (  1.0 4.0)
FPU fmadd (32bit x1) n8           :    0.301    11364.5     5682.3  (  2.0 2.0)
NEON fmul.4s (32bit x4) n12       :    0.226    45347.7    11336.9  (  4.0 4.0)
NEON fadd.4s (32bit x4) n12       :    0.226    45353.3    11338.3  (  4.0 4.0)
NEON fmla.4s (32bit x4) n12       :    0.448    45813.8     5726.7  (  8.0 2.0)

まとめると以下の通りです。

s-adds-muls-fmav-addv-mulv-fma
Cortex-A5522211164bit x2
Cortex-A78222222128bit x2
Cortex-X1442442128bit x4

関連エントリ

Meta Quest シリーズの価格変化のまとめ

Meta Quest (Oculus Quest) の価格の変動をまとめてみました。

2019/052020/092021/072022/082023/032023/062023/102024/01
Quest 1 64GB$399
49800
Quest 1 128GB$499
62800
Quest 2 64GB$299
37180
Quest 2 128GB$299
37180
$399
59400
変更なし$299
47300
変更なし$299
39600
Quest 2 256GB$399
49280
変更なし$499
74400
$429
64405
$349
53900
変更なし$349
46200
Quest 3 128GB$499
74800
変更なし
Quest 3 512GB$649
96800
変更なし

Meta Quest3 の CPU (Snapdragon XR2 Gen2)

Meta Quest 3 は今年 (2023年) の 10月に発売されたばかりの最新の VR ヘッドセットです。Inside Out のセルフトラッキングのみで 6.6DoF を実現する Quest シリーズの 3世代目であり、カラーパススルーに対応したことで MR ゲームもプレイできるようになりました。

シースルー型の HoloLens と違い、ディスプレイ部が視界の一部のみに限られていることもありません。HoloLens に期待していた世界が Quest3 でようやく現実になったといえます。

MR 機能だけでなく、世代が上がりプロセッサもトラッキングも強化されています。特にコントローラーはトラッキング用の LED リングが無くだいぶ小さくなりました。VR というより Switch のような左右分離型のただのゲームコントローラーに見えます。

その Quest3 で以前 Termux が動くことを確認したので同時に vfpbench も走らせてみました。ただし実行中も画面の描画やトラッキングは行われていたため、結果の値には注意が必要です。プロセッサ自体のピーク性能ではなく、GPU やトラッキングにリソースが奪われている状態での結果と思ってください。

スペックによると Quest 3 のプロセッサは Qualcomm Snapdragon XR2 Gen2 が採用されていることがわかります。

https://www.meta.com/jp/quest/quest-3/#specs

計測結果は以下の通り

vfpench MetaQuest3

アプリケーションから見えるプロセッサは 6 Core で 2+4 の 2グループでした。

CPU Thread:  6
CPU Core  :  6
CPU Group :  2
  Group 0: Thread= 2  Clock=2.054400 GHz  (mask:3)
  Group 1: Thread= 4  Clock=2.361600 GHz  (mask:3c)

この両グループの結果を比べてみると、各命令の IPC には明確な差がなくクロック以外はほぼ同等となっています。そのため同じ CPU core が使われている可能性があります。なおこの情報だけではプロセッサの種類まで特定することはできませんでした。

NEON fmul.2d (64bit x2) n12       :    0.819     5189.4     2594.7  (  2.0 1.1)
NEON fadd.2d (64bit x2) n12       :    0.816     5209.8     2604.9  (  2.0 1.1)
NEON fmla.2d (64bit x2) n12       :    0.819    10376.6     2594.1  (  4.0 1.1)

64bit と 128bit に差がないのでリトルコアではなく、また fma と mul/add の差もないため、X1~X3 のようなハイエンドコアでも無さそうです。ただし計測結果はミドルコアのクロックにしてはあまり高くないので、バックグラウンドでパフォーマンスが奪われていたのかもしくは動作中に想定よりクロックが落ちていた可能性があります。この結果はあくまで参考程度でお願いします。

Total:
SingleThread HP max:   42.163 GFLOPS
SingleThread SP max:   21.240 GFLOPS
SingleThread DP max:   10.445 GFLOPS
MultiThread  HP max:  263.868 GFLOPS
MultiThread  SP max:  134.370 GFLOPS
MultiThread  DP max:   63.517 GFLOPS

関連エントリ