
llama.cpp、啟動 OpenAI 相容 API,以及控制 16GB 統一記憶體的使用量。
在 Jetson Orin NX 安裝 llama.cpp 前的環境
- NVIDIA Jetson Orin NX 16GB
- 單一 GPU:
CUDA0 llama.cppCUDA build- NVIDIA Nemotron 3 Nano 4B,GGUF
Q4_K_M量化 - Context length:65,536 tokens
- Parallel slot:1
- 服務入口:
llama-server
以下指令可以作為安裝範本,但 JetPack、CUDA 與套件版本會改變。請先檢查自己的主機,不要直接假設版本與我的環境完全相同。
步驟一:確認 Jetson 與 CUDA 環境
uname -m
cat /etc/nv_tegra_release
nvcc --version
nvidia-smi 2>/dev/null || true
free -h
df -h
uname -m 應顯示 aarch64。Jetson 上不一定能從 nvidia-smi 得到與桌上型顯示卡相同的資訊,因此也可以使用:
sudo tegrastats
tegrastats 會持續輸出 RAM、CPU、GPU、溫度與功耗狀態;按 Ctrl+C 結束。正式調校前,至少要記下 JetPack、CUDA、可用記憶體與儲存空間,否則後續看到編譯失敗或 Out of Memory 時,很難判斷真正原因。
步驟二:安裝編譯工具
sudo apt update
sudo apt install -y git cmake build-essential ccache libcurl4-openssl-dev
這裡假設 CUDA 已經隨 JetPack 正確安裝。如果 nvcc --version 找不到指令,應先修復 JetPack/CUDA 環境,而不是額外安裝一般 Ubuntu 的 nvidia-cuda-toolkit 來混用不同版本。
步驟三:取得並編譯 llama.cpp
cd /opt
sudo git clone https://github.com/ggml-org/llama.cpp.git
sudo chown -R "$USER":"$USER" /opt/llama.cpp
cd /opt/llama.cpp
cmake -S . -B build
-DGGML_CUDA=ON
-DCMAKE_BUILD_TYPE=Release
-DGGML_BUILD_TESTS=OFF
cmake --build build --config Release -j 8
-DGGML_CUDA=ON 是目前官方文件使用的 CUDA 編譯選項。網路上的舊文章可能仍使用 LLAMA_CUBLAS 或 LLAMA_CUDA;這些不是目前應採用的參數。
編譯完成後先確認執行檔與 CUDA device:
cd /opt/llama.cpp
./build/bin/llama-cli --version
./build/bin/llama-cli --list-devices
若採用 shared libraries,手動執行時可能遇到 libllama-common.so.0 找不到的錯誤。我的服務腳本會設定:
export LD_LIBRARY_PATH=/opt/llama.cpp/build/bin:${LD_LIBRARY_PATH:-}
也可以選擇在編譯時加入 -DBUILD_SHARED_LIBS=OFF 產生較容易搬移的靜態版本,但每次更新後仍應重新測試。
步驟四:準備 GGUF 模型
llama.cpp 主要使用 GGUF。Jetson Orin NX 16GB 建議先從 3B~4B 的 Q4_K_M 模型開始,再依實測記憶體決定是否嘗試 7B/8B。不要只看模型檔案大小,因為執行時還需要 KV cache、CUDA compute buffer、作業系統與其他服務的空間。
mkdir -p /home/$USER/models/my-model
# 將已確認授權與來源的 GGUF 模型放進此目錄
ls -lh /home/$USER/models/my-model/*.gguf
模型下載網址與存取權會因模型授權而異,因此本文不放一條看似通用、實際可能失效的下載指令。下載後至少應核對來源頁面、授權、檔案大小與 checksum。
步驟五:先以前景模式測試
cd /opt/llama.cpp
export LD_LIBRARY_PATH=/opt/llama.cpp/build/bin:${LD_LIBRARY_PATH:-}
./build/bin/llama-server
--model /home/$USER/models/my-model/model.Q4_K_M.gguf
--host 127.0.0.1
--port 8080
--n-gpu-layers 99
--ctx-size 8192
--parallel 1
--threads 8
--flash-attn on
第一次不要急著開 64K context。先用 8K 確認模型可以載入、CUDA layers 確實 offload、API 能回覆,再逐步提高 context。
在另一個終端測試 API:
curl http://127.0.0.1:8080/v1/chat/completions
-H 'Content-Type: application/json'
-d '{
"model": "local-model",
"messages": [
{"role": "user", "content": "請用一句話介紹 Jetson Orin NX。"}
],
"temperature": 0.2,
"max_tokens": 80
}'
看到 HTTP 成功回應還不夠。啟動 log 應同時顯示 CUDA device、GPU offload layers 與模型 context;再搭配 tegrastats 觀察 GPU 是否真的有負載。
步驟六:建立 systemd 常駐服務
確認前景測試正常後,再建立服務。以下是一個簡化範例:
[Unit]
Description=llama.cpp CUDA Server
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=roy
WorkingDirectory=/opt/llama.cpp
Environment="LD_LIBRARY_PATH=/opt/llama.cpp/build/bin"
ExecStart=/opt/llama.cpp/build/bin/llama-server
--model /home/roy/models/my-model/model.Q4_K_M.gguf
--host 127.0.0.1
--port 8080
--n-gpu-layers 99
--ctx-size 65536
--parallel 1
--threads 8
--flash-attn on
--cache-type-k q8_0
--cache-type-v q4_0
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
將內容存為 /etc/systemd/system/llama-server.service 後:
sudo systemctl daemon-reload
sudo systemctl enable --now llama-server.service
systemctl status llama-server.service --no-pager
journalctl -u llama-server.service -n 100 --no-pager
API 如果只供同一台 Jetson 上的 Hermes 或其他服務使用,建議綁定 127.0.0.1。若改為 0.0.0.0,就必須另外考慮驗證、TLS、防火牆與網段存取控制,不能把沒有保護的模型 API 直接暴露到網際網路。
Jetson 上最有效的 llama.cpp 優化
一、先選對模型量化
對 16GB 裝置而言,GGUF Q4_K_M 通常是模型品質、載入大小與速度之間的實用起點。更低位元量化可以節省空間,但輸出品質可能下降;較高精度則會壓縮留給 KV cache 與其他服務的記憶體。
二、開啟 CUDA offload
--n-gpu-layers 99 的意思是盡量將所有可 offload 的 layers 放到 GPU。實際數量仍由模型架構決定,因此要看啟動 log,不應只根據指令推定成功。
三、啟用 Flash Attention
--flash-attn on 可降低注意力運算的記憶體流量,長 context 尤其值得測試。不過支援情況會受到模型與 llama.cpp 版本影響;更新後應重新跑相同 prompt 的基準測試。
四、控制 context 與 parallel slots
Context 並不是免費的。從 8K 提高到 64K,KV cache 會明顯成長;--parallel 2 也可能需要更多記憶體。我的用途以個人 Agent 為主,因此保留 64K context,但只使用一個 parallel slot。
五、量化 KV cache
這是我的 Jetson 上最有感的調整:
--cache-type-k q8_0
--cache-type-v q4_0
在 Nemotron 4B Q4_K_M、64K context、單一 slot 的配置下,程序 RSS 約從 5.89GB 降到 4.21GB,釋放約 1.68GB;短 API 測試仍然成功。這是特定主機與模型的實測,不代表每個模型都會得到相同比例,也不代表完全沒有精度代價。
六、不要一開始就調整 swap 與 zram
我的主機在 KV cache 優化後已取得足夠空間,因此保留原有 zram/swap 設定。Swap 可以降低直接 OOM 的機率,卻無法取代真正的記憶體;推論大量換頁時,延遲仍可能惡化。正確順序應是先縮減模型、context、parallel 與 cache,再決定是否調整 swap。
七、固定電力與散熱條件後再測速
Jetson 的效能會受到 power mode、時脈與溫度影響。若要比較設定,應在相同電力模式、散熱狀態、prompt、輸入長度與輸出 token 數下測量,並記錄:
- Prompt processing tokens/s
- Generation tokens/s
- First-token latency
- RSS/可用 RAM/swap
- 溫度、功耗與是否 throttling
我目前採用的配置
我的 Jetson Orin NX 目前以 llama.cpp 作為正式模型服務。GGUF 模型容易管理,OpenAI 相容 API 能直接接上 Hermes,而且 64K context 經過 KV cache 量化後,記憶體已從約 5.89GB 降到 4.21GB,現有服務仍維持正常。
本地 AI 的最佳化不是把所有參數都開到最大,而是找到最符合硬體、模型與實際工作負載的組合。對 16GB Jetson 來說,可維護、可量測與不會頻繁 OOM,通常比單一次跑出最高 tokens/s 更重要。
參考資料