まず、本当にAI推論を行ううえでWindowsを削除して、Ubuntuをインストールしてもよいかを確認します。
1. EVO-X2にUbuntuを導入する判断は正しいか?
最新のハードウェア、特にAIアクセラレータ(NPU)を搭載したプロセッサの能力を最大限に引き出す上で、Ubuntu(Linux)には大きな利点があります。
- AI開発エコシステム: TensorFlow, PyTorch, JAXといった主要な機械学習フレームワークや、推論を高速化するライブラリ(ONNX Runtimeなど)は、もともとLinux環境を第一に開発・テストされています。Dockerを使った環境構築も、Linuxの方がネイティブで遥かにスムーズかつ高パフォーマンスです。
- ドライバの先行提供: AMDは、自社のGPUをAI計算に使うためのプラットフォーム「ROCm」や、新しいNPU用のドライバを、Linux向けに積極的に提供しています。Windows向けにも提供されますが、最先端の機能や最適化はLinuxに先行して投入されることが多いです。
- パフォーマンスと透明性: OS自体が軽量であり、バックグラウンドで動作する不要なサービスを細かく制御できるため、計算リソースをAIタスクに集中させやすいです。何がメモリやCPUを消費しているのかを追跡・管理するツールも豊富です。
つまり、最先端のAIハードウェアのポテンシャルを骨の髄までしゃぶり尽くすには、Linuxの方が適している場面が多いのです。
2. メモリ管理の柔軟さ:UbuntuとWindowsのキャッシュに対する思想の違い
そして、ここからが本題です。
「Ubuntuは推論中でもキャッシュを自動で整理してくれるけど、Windowsは一度使ったキャッシュをずっと握りしめたまま」という体感は、まさに両OSのメモリ管理の思想の違いを的確に捉えています。
私から見ると、これは以下のように見えます。
Windowsのメモリ管理:『几帳面な秘書』
- 思想: 「一度使った書類(データ)は、またすぐ使うかもしれないから、机(RAM)の上にすぐに取り出せるように置いておこう。」これがスタンバイリスト(Standby List)と呼ばれるキャッシュの仕組みです。
- 挙動: アプリケーションがファイルを読み込むと、そのデータはRAM上にキャッシュされます。アプリケーションが終了しても、そのキャッシュは「スタンバイ」として保持されます。これは、次に同じアプリやファイルを開くときに高速化するためで、一般的なデスクトップ利用では非常に効果的です。
- AI推論での問題点: ComfyUIで連続生成を行うようなタスクでは、「モデルAをロード → 推論 → メモリ解放 → モデルBをロード → 推論…」というサイクルが高速に繰り返されます。Windowsは、解放されたはずのメモリをすぐには完全な「空き」にせず、「スタンバイ」として”とりあえず保持”します。新しいメモリ確保の要求があると、OSはスタンバイリストを整理して空き容量を作ろうとしますが、この整理がAIの高速な要求サイクルに追いつかないことがあります。その結果、まだ利用可能なキャッシュがあるにも関わらず、アプリケーション側からは「メモリが足りない」と判断され、エラーが発生します。まさしく「キャッシュを握りしめたまま」の状態です。
Ubuntu (Linux) のメモリ管理:『臨機応変な現場監督』
- 思想: 「空いている作業台(RAM)があるなら、道具(データ)を広げておいて作業効率を上げよう。でも、新しい大きな資材(メモリ確保要求)が来たら、今使っていない道具はすぐに片付けて場所を空けるぞ!」これがページキャッシュ(Page Cache)の仕組みです。
- 挙動: Linuxも、空いているメモリを積極的にファイルキャッシュに利用します。思想はWindowsと似ています。
- AI推論での挙動: 決定的な違いは、メモリが圧迫された時(メモリプレッシャーが高い時)の応答性です。ComfyUIのようなアプリが巨大なメモリ(例:数GBのモデルデータ)をドカッと要求すると、Linuxカーネルはそれを「緊急性の高い要求」と判断し、優先度の低い古いキャッシュを積極的に、かつ迅速に破棄して、要求されたメモリ空間を確保しようとします。この動きが非常に俊敏なため、ユーザーからはあたかも「推論中に自動でキャッシュを整理してくれている」ように見えます。
私の視点
この観察は、単なる体感ではなく、両OSのカーネルレベルでの設計思想の違いに根差した、技術的に正確なものです。
| 項目 | Ubuntu (Linux) | Windows |
| 基本思想 | 空きメモリは積極的にキャッシュに使うが、要求があれば即座に明け渡す(臨機応変) | 空きメモリは将来の高速化のためにキャッシュとして保持することを優先する(事前準備) |
| キャッシュの扱い | メモリプレッシャーに応じて動的かつ迅速に解放 | スタンバイリストとして保持し、解放の判断が比較的緩やか |
| AI推論での挙動 | 大規模なメモリ要求に俊敏に応え、メモリ不足が起きにくい | 高速なメモリ確保・解放の繰り返しで、キャッシュの整理が追いつかずメモリ不足を起こしやすい |
| ユーザーの体感 | 柔軟で、自動で整理してくれる | 一度掴んだものを離さない、握りしめている |
これらの理由で、Ubuntuをインストールした実践記録が下記の内容です。
はじめに
今回、EVO-X2ミニPCにUbuntuをインストールしました。このマシンはGMKtecによると、EVO-X2 AMD Ryzen AI Max+ 395という名称です。まさにコスパに優れた高性能ミニPCです。
EVO-X2のスペック:実装RAM 128GB、ストレージ 1.82TB
EVO-X2実機の前面パネル
本記事では、初期セットアップ(Windowsでの初期不良確認)からUbuntuのネットワークインストールまでの実践的な手順を解説します。
インストールの流れ:
- Windowsで初期起動確認(ハードウェアの初期不良チェック)
- Windowsを完全削除
- UbuntuをPXEネットワークブート経由でインストール
主なスペック
| 項目 | 仕様 |
|---|---|
| CPU | AMD Ryzen AI 9 HX 395 MAX(Zen 5、8コア/16スレッド) |
| GPU | Radeon 890M(RDNA3、16 CU)統合 |
| NPU | Ryzen AI XDNA2 Engine(約50 TOPS) |
| メモリ | LPDDR5X 128GB(CPU/GPU/NPU共有、UMA構成) |
| ストレージ | 1.82TB SSD |
注意: 「GPUが搭載されていない」のではなく、外付けカードがないだけでSoC内にGPUコアが統合されています。
1. 初期セットアップ:キーボード問題への対処
初期起動時のキーボード認識
初回セットアップ時、キーボードが認識されないと作業が進みません。ワイヤレスキーボードでも、USBレシーバー方式であれば初期セットアップ時から認識されます。
Bluetoothキーボードは初期段階では使えないことが多いため、以下のいずれかを推奨します:
- USBレシーバー付きワイヤレスキーボード(推奨)
- 有線USB接続キーボード
Windowsでの初期不良確認
EVO-X2にはWindowsがプリインストールされていたため、まずWindowsで正常に起動することを確認しました。これにより、ハードウェアに初期不良がないことを確認できます。
確認後、Windowsは完全に削除し、Ubuntuをクリーンインストールします。
2. なぜUbuntu?メモリ効率の技術的比較
Windows vs Ubuntu のメモリ管理
AI推論やコンテナ環境を活用する場合、Ubuntuの方がメモリ効率が優れています。
比較表
| 比較項目 | Windows | Ubuntu(Linux) |
|---|---|---|
| 初期使用メモリ量 | 高い(OSが常駐サービス多数) | 低い(デーモンが少なく、軽量) |
| AI推論時のメモリ管理 | GPUメモリをドライバが仮想化・分割管理 | GPUメモリを直接利用(オーバーヘッド少) |
| I/Oキャッシュ | システムキャッシュが肥大化しやすい | 必要最小限で安定 |
| Docker / ROCm 互換性 | 実行時にWSL層を経由 | ネイティブ実行、全メモリを直接管理 |
| NPU / GPU API | DirectML / ONNX Runtime | ROCm / CUDA / OpenCL / Vulkan — より直接的 |
| 実測(同構成) | VRAM使用率が +10〜20%高い | 同モデルでより小さく動く傾向 |
技術的な理由
① OSカーネルのメモリオーバーヘッド
Windows:
- GUIサブシステム(Win32/GDI)、サービス群(Defender、Telemetry、Audio stack等)が常時数GBを占有
- AI実行前に約4〜6 GBがすでに使用中
Ubuntu:
- CUI環境ならベース使用量は600〜900 MB程度
- 推論時の空きメモリが広く、キャッシュ衝突が少ない
② GPUドライバのメモリ予約方式
WindowsのWDDM (Windows Display Driver Model) は「仮想VRAM」を複数アプリで共有しようとするため、実際にはGPUの実VRAMより多く見せて管理します。その結果、AIフレームワークが実VRAMを確保しようとすると、最初から数百MB〜数GBが「システム予約」扱いになります。
Ubuntu(amdgpu/ROCmやnvidia-driver) では、カーネルモジュールが直接メモリを管理するため、無駄な「仮想予約」領域が発生しません。
③ Docker や PyTorch の挙動
Windows上では:
- Docker Desktop → Hyper-V/WSL2 → Linux VM → コンテナという多段構造
- メモリとGPUアクセスにレイヤーが増える
Ubuntu では:
- Dockerがネイティブで動くため、
--gpus allでGPUメモリを直接コンテナへ割当可能 - 転送効率が高く、初期確保メモリも少ない
④ キャッシュとページング
Ubuntuはメモリ管理が柔軟で、AI推論中にキャッシュを自動開放します。一方Windowsは「一度キャッシュしたメモリを保持し続ける」傾向があり、メモリ不足を引き起こしやすいです。
特にComfyUI / Stable Diffusionなどでは、Ubuntuの方が長時間連続稼働しても安定します。
3. BIOS設定
Ubuntuをインストールする前に、BIOS設定を変更する必要があります。
3-1. セキュアブートの無効化
セキュアブートを無効にする理由:
実際に経験したトラブルとして、Ubuntuでディスプレイドライバを更新した際、セキュアブートが有効だとシステムが起動しなくなったことがあります。
このため、Ubuntuを使用する場合はセキュアブートを無効にすることを推奨します。
3-2. ブート順序の変更
ネットワークブートでUbuntuをインストールするため、ブート順序でネットワークを最優先に設定します。
BIOS Boot設定:Boot Option #1をNetworkに設定
設定項目:
- Boot Option #1: Network(PXEブート用)
- Boot Option #2: NVME(内蔵SSD)
- Boot Option #3: Hard Disk
- Boot Option #4: USB Device
- Boot Option #5: CD/DVD
4. PXEネットワークブートによるインストール
PXEブートの利点
今回はUSBメディアではなく、PXEネットワークブートでUbuntuをインストールしました。
PXEブートの利点:
- USBメモリ不要
- 複数のOSから選択可能
- ネットワーク経由で最新のインストーラーを取得
- 再利用性が高い(一度サーバーを構築すれば何度でも使える)
PXEブート起動画面:iPXE 1.21.1+でNBPファイルをダウンロード
DHCPサーバーとPXEサーバーの構築について
DHCPサーバーやネットワーク関係、PXEについて知りたい方はこちらを参考にしてください:
上記のリンク先で、10年前のPCでも十分動作するPXE/DHCPサーバーの構築方法を詳しく解説しています。
PXEブート以外の代替案
外付けデバイスなしでOSをインストールする方法は、他にも以下のようなものがあります:
① UEFI HTTP Boot / iPXE
PXEの”兄弟”技術。TFTPではなくHTTPでイメージを取得する方式。
② GRUBのloopback起動
ISOを内蔵SSDのパーティションに配置し、GRUBから直接ISOを起動する方法。
③ ディスクレス起動(iSCSI / NFS-root)
ストレージをネット側に置いてOSを起動する方式。
実運用では、PXE(またはHTTP Boot)が最もラクで再現性も高いです。
5. インストール時の注意点
再起動時の対処
ネットワークインストール中、途中で再起動が発生します。この際、再度ネットワークブートしてしまうと、インストールが最初からやり直しになってしまいます。
対処方法(いずれか):
- 再起動時にネットワーク接続を切断する
- BIOSの起動順序を元に戻す(内蔵ストレージを最優先に)
インストール完了後は、ブート順序を以下のように戻しておくことを推奨します:
- 内蔵ストレージ(SSD)
- ネットワーク
次のセクション(SSH接続設定)に続きます…
(1) PowerShellで鍵と接続を準備 → (2) VS CodeのRemote-SSHで入る
手順(Windows → Ubuntu)
🖥️ 1) Windows側でSSH鍵を作成
以下は Windows(ユーザー名:minok) で実行します。
# すでに C:\Users\minok\.ssh\id_ed25519 がある場合はスキップ
ssh-keygen -t ed25519 -C "minok@win" -f $env:USERPROFILE\.ssh\id_ed25519
-Cはコメント(識別用ラベル)です。
→ 実際の接続とは無関係で、好きな名前にして構いません。
例:"minok@win"、"mamu@desktop"、"project-key-2025"など。
📁 生成されるファイル(Windows側):
C:\Users\minok\.ssh\id_ed25519
C:\Users\minok\.ssh\id_ed25519.pub
💡 注意
すでにGitHubやサーバー用の鍵がある場合、上書きせずに別名を指定してください。
ssh-keygen -t ed25519 -C "minok@win" -f "$env:USERPROFILE\.ssh\id_mamu_2025"
🌐 2) 公開鍵をUbuntuへコピー
次は WindowsのPowerShell で実行します。
(リモート側のユーザーは mamu です)
type $env:USERPROFILE\.ssh\id_ed25519.pub `
| ssh mamu@192.168.0.108 `
"umask 077; mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys && chown -R mamu:mamu ~/.ssh"
- 右側(
ssh mamu@192.168.0.108)のユーザーは Ubuntu側のユーザー名 - 左側(
$env:USERPROFILE)は Windowsのユーザー(minok) - 初回接続時のみパスワード入力を求められます(Ubuntuインストール時に設定したもの)
✅ 安全&確実版
- 公開鍵の読み出しは
Get-Content -Rawにすると“1行のまま”渡せて安心。 - リモート側コマンドはシングルクォート
'...'で囲むと、PowerShellに解釈されずそのまま送れる。
(~展開・>>リダイレクトはリモート側のシェルで効く)
修正版ワンライナー(Windows PowerShell)
Get-Content -Raw $env:USERPROFILE\.ssh\id_ed25519.pub `
| ssh mamu@192.168.0.108 `
'umask 077; mkdir -p ~/.ssh && touch ~/.ssh/authorized_keys && chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys && cat >> ~/.ssh/authorized_keys'
どこが「より確実」だったかだけ整理
typevsGet-Content -Rawtype(= Get-Content)は行配列で渡す挙動。公開鍵は1行なので通常OKですが、-Rawだと「必ず1行の文字列」で渡せて事故りにくい。- リモート側コマンドのクォート
PowerShellの'...'で包むと、変数展開や~の解釈がリモート側に確実に渡る(ローカルで解釈されにくい)。 - 権限を決めてから追記
touch → chmod → cat >>の順は、たまに起きる「authorized_keys の権限が広すぎて拒否」を防ぐための順番チューニング。 - chown 省略
自分のホームに自分で書くなら不要。もしsudoで作った等なら、その時だけchown -Rを入れるのが正解。
失敗すると以下のようになります。
ssh: connect to host 192.168.0.108 port 22: Connection refused
🧩 原因の切り分け:Connection refused の意味
ssh: connect to host 192.168.0.108 port 22: Connection refused
これはファイアウォールでブロックされたのではなく、
「ポート22にリッスンしているプロセス(sshd)が存在しない」という意味です。
✅ 対処手順(Ubuntu側)
1️⃣ SSHサーバーが入っているか確認
dpkg -l | grep ssh
- 何も出ない場合はまだインストールされていません。
openssh-serverがあればOK。
2️⃣ SSHサーバーをインストール
sudo apt update
sudo apt install -y openssh-server
3️⃣ サービス起動と自動起動設定
sudo systemctl enable --now ssh
これで即座に起動し、次回から自動起動します。
4️⃣ 状態確認
sudo systemctl status ssh
出力例:
● ssh.service - OpenBSD Secure Shell server
Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled)
Active: active (running)
→ active (running) なら通信できる状態。
5️⃣ 念のためポート確認
sudo ss -tlnp | grep ssh
出力例:
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1234,fd=3))今までは、Ubuntu Serverインストール時にopenssh-serverにチェックを入れなくてもSSH接続できていました。しかし、以下の原因があるようです。
🧩 なぜ「OpenSSH を入れなくても接続できる」場合があるのか
✅ 1. Server エディションやCloud イメージ(EC2, OCI, Multipassなど)の場合
これらは最初から openssh-server がインストール済みで、sshd サービスも有効化されています。
たとえば:
sudo systemctl status ssh
# → active (running)
このため、チェックを入れなくてもSSH接続が通るように見えます。
(=「入れた覚えがないのに繋がる」現象)
⚙️ 2. Desktop版でもプリインストールされるケース
Ubuntu Desktop(特に22.04以降)では、
「OpenSSH Server」を選択しなくても openssh-client は必ず入ります。
また、一部のISOでは openssh-server も既に入っていることがあります。
特に:
- OEMビルド
- WSLでのUbuntu
- 一部のMinimal構成ではないISO(例:Ubuntu Desktop Full Install)
これらはユーザーがチェックを外しても、バックグラウンドで含まれる場合があります。
🧩 3. 再利用イメージやCloud-initの影響
過去にSSHを有効化したディスクやテンプレートを使うと、sshd の設定・鍵・サービスが引き継がれます。
この場合、「新規インストールしたつもり」でも
実際には ~/.ssh や /etc/ssh/ssh_host_* が残っており、再度動作可能な状態です。
もしかすると上記の理由云々より、Ubuntu25.04から正確になったのかもしれません。
⚙️ 3) 接続確認
ssh -i $env:USERPROFILE\.ssh\id_ed25519 mamu@192.168.0.108
「Welcome to Ubuntu…」のように表示されれば成功です。
🧩 4) SSH設定ファイルで簡略化(推奨)
PowerShellで以下を実行:
notepad $env:USERPROFILE\.ssh\config
もしくは以下のフォルダのconfigファイルをメモ帳などで開きます。
C:\Users\minok.ssh開いたら追記します:
Host ubuntu108
HostName 192.168.0.108
User mamu
IdentityFile C:\Users\minok\.ssh\id_ed25519
IdentitiesOnly yes
Port 22
保存後、以降は簡単に:
ssh ubuntu108
💡 トラブル回避のための補足
| 状況 | 安全な対応 |
|---|---|
| 既存の鍵を上書きしそう | 鍵ファイルをバックアップ or 別名で作成 |
| 複数サーバーで使う | 鍵ごとにコメントやファイル名を変える |
| どの鍵を登録したか忘れそう | 公開鍵を .txt にまとめてメモしておく |
バックアップ方法(Windows PowerShell):
Copy-Item $env:USERPROFILE\.ssh $env:USERPROFILE\.ssh_backup -Recurse
🧩 5) VS Code で接続(Remote-SSH)
1️⃣ 拡張機能のインストール
VS Code の拡張機能マーケットプレイスから
🔹 Remote – SSH をインストールします。
2️⃣ 接続設定
コマンドパレット(Ctrl + Shift + P)→Remote-SSH: Connect to Host... を選択。
先ほど ~/.ssh/config に設定したエイリアス ubuntu108 を選択します。
左下の緑色ステータスバーにSSH: ubuntu108 と表示されれば接続成功です。
初回は「Linux / Ubuntu」を選び、
VS Code がリモート側に自動で VS Code Server をインストールします。
3️⃣ サーバー側(Ubuntu)で確認したいこと
| チェック項目 | コマンド | 状態 |
|---|---|---|
| SSH サービス稼働 | sudo systemctl status ssh | active (running) であること |
| 無効な場合 | sudo systemctl enable --now ssh | 起動と自動起動設定 |
| 鍵認証が通らないとき | chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys | パーミッション修正 |
💡 ファイアウォール説明は省略OK
通常、ローカルLAN内やクラウド初期設定直後ではポート 22 は既に開放済み。sudo ufw allow 22/tcpなどは必要な場合だけ付録として触れる程度で十分です。
4️⃣ 鍵ログインを強化(任意)
より安全にする場合のみ設定します。
sudoedit /etc/ssh/sshd_config
# 以下を確認・変更
PubkeyAuthentication yes
PasswordAuthentication no # パスワードログイン無効化
変更後は再読み込み:
sudo systemctl reload ssh
5️⃣ トラブル時のチェックリスト
✅ IP アドレスが変わっていないか(DHCP で変わることあり)
✅ User 名が正しいか(例:mamu)
✅ ~/.ssh/config の IdentityFile パスが正しいか
✅ 22 番ポートがブロックされていないか(セキュリティソフト・ルーター設定)

