Intel NUCのGPUを使ってローカル LLM

投稿者: | 9月 5, 2025

Intel GPUを使ってみた!の最終回。ほんと時間の無駄だった。常磐線の普通列車くらいはスピードでるかと思ったら、常磐線の各駅停車より酷いといいたい。大学時代、入学式が終わった後、「東京1」という、「東京1年生」みたいな小冊子を配っている人たちがいた。自分は、生まれも育ちも東京なのでいらないなぁと思っていたが、つい受け取ってしまった。そこに書かれていたのが、「常磐線の普通と各駅停車の違い」だった。よく考えたら知らなかった。平たくいうと、普通は、上野から、常磐線への遠くへ行く、各駅停車は、千代田線から来る取手までの電車。停車駅数が全然違う。そういえば、昔は、新宿駅からも中央線で、総武緩行線と普通が出ていた。新宿を起点にすると総武緩行線は、大久保ー三鷹まで完全に各駅、普通は、中央快速の線路を使い、新宿を出ると次の駅は立川だった。ただ、中央快速の隙間を縫っていくので、体感速度は総武緩行線より遅い。はっきり言って鬱になるくらい遅く感じた。

Intel CPU内蔵のGPUの体感速度は、総武線よりも中央線に近いかもれない。遅い、遅いといっているのは、Intel 第11,12世代のNPUが積んでいない世代を言っているのだが。。。

 

閑話休題

 

Intel NUCのGPUを使ってローカルLLMを作ってみた。第11、第12世代までをターゲットにしている。また、これも、期待はガスなので、時間が有り余っている人以外は、読むだけにしておくべき。

 

環境

  物理: Intel NUC 第12世代 12th Gen Intel(R) Core(TM) i7-1260P. Memory 64GB M2.NVME 1TB

     ESXi 8.0u2 

  仮想マシン: 8 core 32GB RAM 200GB HDD GPUをPCIパススルーにしてある。

     Ubuntu Server 24.04最新 amd64 クリーンインストールで、docker CEがインストールしてある。

仮想マシンでDockerなので、屋上屋を架している感が否めないが。。。以下、作業部分は、なんかやっているなぁと言う生暖かい目で見ていただき(試して欲しく無いのでざっくり殴り書き)、最後の結論を読んでいただきたい。

 

1. 前準備

# 作業ディレクトリ作成
cd ~
mkdir llm-stack
cd llm-stack
# サブディレクトリ作成
mkdir -p models open-webui/data

 

2. compose.yaml 作成

cat > compose.yaml <<‘EOF’
services:
ipex-llm:
  image: intelanalytics/ipex-llm-inference-cpp-xpu:latest
  container_name: ipex-llm
  command: ["bash","-lc","/workspace/start-llama.sh”]
  ports:
    - "8000:8000”
  devices:
    - /dev/dri:/dev/dri
  environment:
    - ONEAPI_DEVICE_SELECTOR=level_zero:gpu
    - ZES_ENABLE_SYSMAN=1
    - SYCL_PI_LEVEL_ZERO_USE_IMMEDIATE_COMMANDLISTS=1
  volumes:
    - ./models:/workspace/models
    - ./llama.cpp:/workspace/llama.cpp
    - ./start-llama.sh:/workspace/start-llama.sh:ro
  healthcheck:
    test: ["CMD-SHELL", "/bin/bash -lc 'exec 3<>/dev/tcp/127.0.0.1/8000 && printf \"GET /v1/models HTTP/1.0\\r\\n\\r\\n\" >&3 && head -n1 <&3 | grep -q HTTP’”]
    interval: 15s
    timeout: 5s
    retries: 40
    start_period: 60s
    restart: unless-stopped

openwebui:
  image: ghcr.io/open-webui/open-webui:main
  container_name: open-webui
  environment:
    - OPENAI_API_BASE_URL=http://ipex-llm:8000/v1
    - OPENAI_API_KEY=sk-local
    - DEFAULT_MODEL=gpt-oss-20b
  ports:
    - "3000:8080”
  depends_on:
    ipex-llm:
      condition: service_healthy
  volumes:
    - ./open-webui/data:/app/backend/data
  restart: unless-stopped
EOF

 

3. 起動スクリプト start-llama.sh 作成

cat > start-llama.sh <<‘EOS’
#!/usr/bin/env bash
source /opt/intel/oneapi/setvars.sh || true
set -euo pipefail

MODEL_PATH="$(ls -1 /workspace/models/gpt-oss*.gguf 2>/dev/null | head -n1 || true)”
if [[ -z "${MODEL_PATH}" ]]; then
echo "[ERR] No model found in /workspace/models (expecting gpt-oss*.gguf)”
ls -lh /workspace/models || true
exit 1
fi

if [[ ! -x /workspace/llama.cpp/build/bin/llama-server ]]; then
echo "[INFO] Building llama.cpp (first run)”
apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
  git build-essential cmake pkg-config curl ca-certificates
update-ca-certificates || true
git clone --depth=1 https://github.com/ggerganov/llama.cpp /workspace/llama.cpp
cmake -S /workspace/llama.cpp -B /workspace/llama.cpp/build \
  -DGGML_SYCL=ON -DLLAMA_BUILD_SERVER=ON -DLLAMA_CURL=OFF \
  -DCMAKE_C_COMPILER=icx -DCMAKE_CXX_COMPILER=icpx
cmake --build /workspace/llama.cpp/build -j $(nproc)
fi

echo "[INFO] Starting llama-server with model: ${MODEL_PATH}”
exec /workspace/llama.cpp/build/bin/llama-server \
-m "${MODEL_PATH}” \
--alias gpt-oss-20b \
--host 0.0.0.0 --port 8000 \
-c 2048 --parallel 1 -ngl -1 \
--cont-batching —verbose
EOS

chmod +x start-llama.sh

 

4. モデルの配置(手動)

wget -O /root/gpt-oss-20b-Q4_K_M.gguf https://huggingface.co/unsloth/gpt-oss-20b-GGUF/resolve/main/gpt-oss-20b-Q4_K_M.gguf
cp /root/gpt-oss-20b-Q4_K_M.gguf ~/llm-stack/models/
ls ~/llm-stack/models/

 

5. 起動

docker compose up -d

以下、約6分(376s)かかる。Pull 193s (1Gbps回線) / Running 183s (バイナリを作るため)

 

6. CLI動作確認

# モデル一覧確認
curl -s http://127.0.0.1:8000/v1/models | jq .

# 簡易推論
curl -s http://127.0.0.1:8000/v1/chat/completions \
-H "Authorization: Bearer sk-local” \
-H "Content-Type: application/json” \
  -d '{"model":"gpt-oss-20b","messages":[{"role":"user","content":"Say hello in one word."}]}' | jq .

 

# 非ストリームでのベンチマーク

START=$(date +%s.%N); \
RESP=$(curl -s http://127.0.0.1:8000/v1/chat/completions \
-H "Authorization: Bearer sk-local” \
-H "Content-Type: application/json” \
-d '{"model":"gpt-oss-20b","messages":[{"role":"user","content":"Say hello in one word."}],"stream":false}'); \
END=$(date +%s.%N); \
TOK=$(echo "$RESP" | jq -r '.usage.completion_tokens // 0'); \
ELAPSED=$(echo "$END - $START" | bc); \
TOKS_PER_SEC=$(echo "$TOK / $ELAPSED" | bc -l); \
echo "completion_tokens=$TOK elapsed=${ELAPSED}s tok/s=${TOKS_PER_SEC}"; \
echo "$RESP" | jq .

 

結果

第12世代

completion_tokens=157 elapsed=27.539505537s tok/s=5.70090119407070166235

第11世代

completion_tokens=113 elapsed=15.801424538s tok/s=7.15125397259293610151

第11世代のGPUのほうが速い。

 

7. Web-UI動作確認

WebUI は http://<ホストIP>:3000 でアクセス。

あとは割愛。

 

 

色々やってみたベンチマークはこちら。

Intel 第11世代 GPUなし

root@rlug-dev:~# ./tokps-curl-only.sh OLLAMA http://127.0.0.1:11434 gpt-oss:20b

Generated tokens : 256

Wall seconds : 29.499520

Tok/s (wall) : 8.68

 

Intel 第12世代 GPUなし

root@4lcby-ubuntu2404:~/llm-standard# ./tokps-curl-only.sh OLLAMA http://127.0.0.1:11434 gpt-oss:20b

Generated tokens : 253

Wall seconds : 26.161108

Tok/s (wall) : 9.67

 

Intel 第12世代 GPUあり

root@4lcby-ubuntu2404:~# ./tokps-curl-only.sh LLAMACPP http://127.0.0.1:8000 gpt-oss-20b

Generated tokens : 256

Wall seconds : 42.167389

Tok/s (wall) : 6.07

 

M4 MacBook Air (LM Studio)

bash-3.2$ ./lmstudio-tokps.sh http://127.0.0.1:1234/v1/chat/completions gpt-oss-20b

Generated tokens : 154

Wall seconds : 5.282941

Tok/s (wall) : 29.15

 

レビュー

解せないのでAIにレビューをしてもらったところ、以下のような結果になった。

1. Intel 第11世代 (GPUなし)

– AVX-512 命令が有効で、CPU推論に強い世代。

– ただしクロック周波数やIPCの制約から、Tok/s は 8.68 に留まる。

– CPU単体でも十分に処理できるが、20Bクラスでは性能頭打ち感がある。

2. Intel 第12世代 (GPUなし)

– AVX-512は無効だが、Pコアの性能向上と高クロック化により、第11世代より速い。

– Tok/s は 9.67 と第11世代を上回り、純CPU推論では最速。

– AVX-512無しでも世代性能差が効いている点が注目。

3. Intel 第12世代 (GPUあり)

– iGPU (Xe) を使ったオフロード構成。

– 20Bモデルは巨大で、全層をiGPUに載せられず CPUとの分担処理が必要。

– この時に発生する CPU–GPU間メモリ転送や同期のオーバーヘッドが大きいため、結果的に 6.07 Tok/s とCPU単体より遅くなる。

– → iGPUは 7B/13Bのような中小規模モデルで効率が出やすく、20Bでは逆効果になりやすい。

4. Apple M4 MacBook Air (LM Studio)

– 統合メモリアーキテクチャ + Metal最適化により、推論性能が圧倒的。

– 生成トークン数は154と少なめだが、5.28秒で29.15 Tok/s を達成。

– Intel CPUの3〜5倍のスループットで、かつファンレスモバイル環境で動作するのは Apple Silicon の大きな強み。

– 実時間が短いので、ロード込みの初回計測でも高効率が確認できる。

 

まとめと示唆

– 第12世代CPUは純CPU推論で第11世代を上回る(AVX-512無効でもIPCとクロックで補う)。

– iGPUは20Bには不向き。むしろCPU単体の方が効率が良い。

– Apple M4は圧倒的。Tok/sは Intel CPU系の3倍以上、NPU/GPU最適化と統合メモリが効いている。

– 今後の比較では:

 – 12世代iGPUで7B/13Bを試す → iGPUが活きる条件を見極める。

 – M4でn=256フル生成 → Intel CPUと完全同条件で性能比較。

 – ウォームアップ2回目以降の値を採用 → 初回ロード時間を排除して正確比較。

 

CPUだけで比較すると、Intel 第11世代と第12世代では、第11世代のほうが、AVX-512が使えるのでパフォーマンスがよく、第12世代は、単純なCPUの性能だけで乗り越えている。

また、oss-gptは大きすぎてGPUを有効にすると逆にパフォーマンスが遅い。CPU単体でこなしたほうが速い。

GPUの比較の場合、簡易ベンチマークの結果からすると、GPUの比較でも第11世代のほうが、第12世代よりも速い。

 

結論

Intel 第11世代と第12世代ではCPUだけ使えと。GPUを使うなら、ちゃんとしたGPUがある環境が必要。Intel GPUはあれば便利に動いてくれるという代物じゃないということに。

M4 MacBook Airの通り、NPU/GPU最適化と統合メモリやメモリ帯域が重要。

 

以前の仕事の都合で、ESXのインフラの検証をするためにIntel CPU+DDR4の機材を持っていたが、今や全部ゴミということが判明。幸いIntel NUCのサイズだと、燃えないゴミとしてポイも可能かと。サーバ機じゃなくてよかった。廃棄するのも一苦労。ブロードコムの問題のおかげクラウドに移行している人も多いので前にも増してインフラサーバなんて誰も欲しく無いだろうし。

 

最後に

今思った、こんな面倒なことしないで、LM Studioのほうが便利。

コメントを残す