TWCC
    • Sharing Link copied
    • /edit
    • View mode
      • Edit mode
      • View mode
      • Book mode
      • Slide mode
      Edit mode View mode Book mode Slide mode
    • Note Permission
    • Read
      • Only me
      • Signed-in users
      • Everyone
      Only me Signed-in users Everyone
    • Write
      • Only me
      • Signed-in users
      • Everyone
      Only me Signed-in users Everyone
    • More (Comment, Invitee)
    • Publishing
    • Commenting Enable
      Disabled Forbidden Owners Signed-in users Everyone
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Invitee
    • No invitee
    • Options
    • Versions and GitLab Sync
    • Transfer ownership
    • Delete this note
    • Template
    • Save as template
    • Insert from template
    • Export
    • Google Drive Export to Google Drive
    • Import
    • Google Drive Import from Google Drive
    • Gist
    • Clipboard
    • Download
    • Markdown
    • HTML
    • Raw HTML
Menu Sharing Help
Menu
Options
Versions and GitLab Sync Transfer ownership Delete this note
Export
Google Drive Export to Google Drive
Import
Google Drive Import from Google Drive Gist Clipboard
Download
Markdown HTML Raw HTML
Back
Sharing
Sharing Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
More (Comment, Invitee)
Publishing
More (Comment, Invitee)
Commenting Enable
Disabled Forbidden Owners Signed-in users Everyone
Permission
Owners
  • Forbidden
  • Owners
  • Signed-in users
  • Everyone
Invitee
No invitee
   owned this note    owned this note      
Published Linked with GitLab
Like BookmarkBookmarked
Subscribed
  • Any changes
    Be notified of any changes
  • Mention me
    Be notified of mention me
  • Unsubscribe
Subscribe
--- title: 在 HPC 系統上透過 Slurm 部署 Ollama --- # 在 HPC 系統上透過 Slurm 部署 Ollama ## 架構 | 節點類型 | 能做什麼 | 不能做什麼 | | ---------------------- | -------- | ---------- | | 登入節點(login node) |安裝執行檔、下載模型檔案、寫 job script、送出 job |不可執行 `ollama serve`(會佔用共用資源、開 port 有資安疑慮)| | 計算節點(compute node)| 透過 Slurm job 執行 `ollama serve` 與推論 | cluster 的計算節點沒有對外網路,無法連線下載模型 | 因為登入節點能上網、但不該跑 service;計算節點能跑 service、但不能上網,所以在登入節點用純 HTTP 下載模型檔案(不啟動 Ollama service),存到計算節點也看得到的共用檔案系統(如 `/work1`),計算節點的 job 啟動後直接讀取 local 檔案。 ``` 登入節點(有網路,不開 service) └─ curl 直接向 registry 下載 manifest + blobs → 寫入 /work1/$USER/ollama_models 計算節點(無網路,共用檔案系統) └─ Slurm job 啟動 ollama serve(僅限內部使用) └─ ollama run 時發現模型已存在本地 → 直接讀取,不連網 ``` # Step 1:安裝 Ollama 執行檔(登入節點) # 不要用官方一鍵安裝腳本 ```bash curl -fsSL https://ollama.com/install.sh | sh ``` 這個腳本需要 `sudo` 權限(建立系統帳號、寫 systemd service),一般使用者在登入節點上沒有這個權限。 # 改用 tarball > ref: https://docs.ollama.com/linux > ```bash mkdir -p ~/ollama_install/extracted cd ~/ollama_install curl -LO https://ollama.com/download/ollama-linux-amd64.tar.zst ``` # 解壓縮 `zstd` 搭配 pipe 的方式解壓縮: ```bash zstd -d -c ollama-linux-amd64.tar.zst | tar -xvf - -C ~/ollama_install/extracted ``` # 驗證安裝並加入 PATH ```bash ~/ollama_install/extracted/bin/ollama --version echo 'export PATH=$HOME/ollama_install/extracted/bin:$PATH' >> ~/.bashrc export PATH=$HOME/ollama_install/extracted/bin:$PATH ``` 如果看到版本號輸出(例如 `client version is 0.31.2`)就代表安裝成功。 # Step 2:下載模型(登入節點,不啟動任何 service) ## 為什麼不能直接用 `ollama pull` `ollama pull` 是 client 指令,實際下載動作是由背景執行的 `ollama serve` 完成的,也就是說要用這個指令,必須先啟動 service,但我們不希望在登入節點跑 service。 ## 解法:直接用 HTTP 向 registry 下載 > ref: https://ollama.com/library > Ollama 模型的manifest 與模型權重都只是透過標準 HTTPS GET 就能取得的靜態檔案。 建立以下下載腳本 `download_model.sh`: ```bash #!/bin/bash set -o errexit set -o nounset MODEL=$1 # 例如 llama3.2 TAG=$2 # 例如 1b MODELS_DIR=/work1/$USER/ollama_models echo "Downloading manifest for $MODEL:$TAG..." mkdir -p $MODELS_DIR/manifests/registry.ollama.ai/library/$MODEL MANIFEST_PATH=$MODELS_DIR/manifests/registry.ollama.ai/library/$MODEL/$TAG curl -sL -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \ https://registry.ollama.ai/v2/library/$MODEL/manifests/$TAG \ -o $MANIFEST_PATH if ! jq empty $MANIFEST_PATH 2>/dev/null; then echo "錯誤:manifest 不是合法的 JSON,請確認 MODEL/TAG 名稱是否正確" cat $MANIFEST_PATH exit 1 fi echo "Manifest downloaded successfully." mkdir -p $MODELS_DIR/blobs digests=$(jq -r '[.config.digest, (.layers[].digest)] | .[]' $MANIFEST_PATH) total=$(echo "$digests" | wc -l) count=0 for d in $digests; do count=$((count+1)) hash=${d#sha256:} blob_path="$MODELS_DIR/blobs/sha256-$hash" if [ -f "$blob_path" ]; then echo "[$count/$total] 已存在,略過: $hash" continue fi echo "[$count/$total] 下載中: $hash" curl -sL "https://registry.ollama.ai/v2/library/$MODEL/blobs/sha256:$hash" \ -o "$blob_path" done echo "全部下載完成:$MODEL:$TAG" ``` 執行方式: ```bash bash download_model.sh llama3.2 1b # 模型可自行更換 ``` # Step 3:Slurm Job Script ## 先建立一個內建 `num_thread` 的衍生模型 > ref:https://medium.com/@kapildevkhatik2/optimizing-ollama-performance-on-windows-hardware-quantization-parallelism-more-fac04802288e > `ollama run` 不像 API 那樣可以直接在請求裡指定 `num_thread`。若不特別設定,Ollama 可能會偵測到整個節點的實體核心數(例如 112),開出遠超過 `--cpus-per-task` 實際分配到的執行緒數量,導致執行緒搶核心、大量 context switch,推論速度可能因此慢上好幾倍甚至更多。 解法是透過 Modelfile 建立一個內建正確 `num_thread` 的衍生模型(只需要做一次,之後重複使用): ``` # Modelfile FROM llama3.2:1b PARAMETER num_thread 8 ``` > `num_thread` 的數值要跟 job script 裡的 `--cpus-per-task` 一致。 > `ollama create` 一樣需要連到正在跑的 server,不能在登入節點執行,必須放進 job script 裡、`ollama serve` 啟動之後執行(見下方腳本)。`Modelfile` 檔案放在 `$HOME` 底下即可,計算節點透過共用檔案系統一樣讀得到。 ```bash #!/bin/bash #SBATCH --account=<PROJECT_ID> #SBATCH --job-name=ollama_test #SBATCH --partition=development #SBATCH --nodes=1 #SBATCH --cpus-per-task=8 #SBATCH --time=00:30:00 #SBATCH --output=./logs/ollama_%j.out #SBATCH --error=./logs/ollama_%j.err set -o errexit set -o nounset export OLLAMA_MODELS=/work1/$USER/ollama_models/ ollama_bin=$HOME/ollama_install/extracted/bin/ollama echo "Running on node: $(hostname)" mkdir -p ./model_logs $ollama_bin serve &> ./model_logs/${SLURM_JOBID}-ollama-server.log & sleep 15 $ollama_bin create llama3.2-fast -f $HOME/Modelfile echo "請用一句話自我介紹" | timeout 180 $ollama_bin run llama3.2-fast >> ./model_logs/${SLURM_JOBID}-modelresponse.txt killall ollama ``` ## 腳本重點說明 * `OLLAMA_MODELS` 要重新 export:即使在登入節點已經設定過這個環境變數,job script 是全新的 shell,必須在腳本內重新宣告一次。 * `sleep 15`:讓 `ollama serve` 有時間完成啟動,才接著呼叫後續指令。 * 用 `echo "prompt" | ollama run <model>`,不要用 `ollama run <model> "prompt"`。`ollama run` 在 Slurm batch(非互動、無 TTY)環境下直接把 prompt 當成命令列參數時,實測會整個卡住、永遠不會送出推論請求,詳見〈常見問題〉。改用管道方式可以繞開這個問題。 * `--cpus-per-task` 給予足夠核心數即可,且要跟 Modelfile 裡的 `num_thread` 對齊。 # Step 4:送出 Job 並驗證 ## 送出 Job ```bash sbatch ollama_service.sh squeue -u $USER ``` ## 確認執行結果 ```bash cat logs/ollama_<JOBID>.err cat model_logs/<JOBID>-modelresponse.txt cat model_logs/<JOBID>-ollama-server.log ``` 若 `.err` 為空、`modelresponse.txt` 有內容,代表整條流程成功。 # 常見問題與解法 ## 問題 1:`llama-server process has terminated: signal: segmentation fault (core dumped)` > 類似問題 https://www.reddit.com/r/LocalLLaMA/comments/1r807kb/segmentation_fault_when_loading_models_across/ https://github.com/ollama/ollama/issues/17006 > **現象**:模型載入完全正常(tensor 讀取、KV cache 配置皆無誤),崩潰精確發生在「warm-up 空跑」或第一次真正推論的階段。 **原因**:新款 Intel Xeon(Sapphire Rapids 世代)搭配較新版本的 Ollama,AMX 加速路徑可能存在相容性問題(實測 v0.31.2 會 crash,降版到 v0.22.0 可解決;確切從哪個版本開始出現此問題,未經官方文件證實,僅為推測)。會在執行運算時 segfault。可透過 log 中出現的這一行確認是否為此問題: ``` load_tensors: AMX model buffer size = ### MiB ``` **排除步驟:** 換不同模型架構/量化格式測試(qwen2.5、llama3.2) ,還是在同個地方崩潰 嘗試 `OLLAMA_LLM_LIBRARY=cpu_icelake` 強制指定非 AMX 的 CPU backend → 實測無效,AMX 是獨立於這個環境變數之外的加速層,不受其控制 改用 v0.30 之前的舊版本(例如 v0.22.0)→ 有效,可能是因為當時 Ollama 尚未整合這套會觸發 AMX 的 llama.cpp 引擎更新。 **解法:安裝舊版本** ```bash mkdir -p ~/ollama_install_legacy/extracted cd ~/ollama_install_legacy curl -LO https://github.com/ollama/ollama/releases/download/v0.22.0/ollama-linux-amd64.tar.zst zstd -d -c ollama-linux-amd64.tar.zst | tar -xvf - -C ~/ollama_install_legacy/extracted ``` ## 問題 2:`Error: pull model manifest: ... dial tcp ... i/o timeout` **原因**:計算節點沒有對外網路,無法連線 registry 下載模型。 **解法**:改用 Step 2 的做法,在登入節點先把模型下載到共用檔案系統,計算節點的 job 直接讀取本地檔案,完全避開連網需求。 ## 問題 3:`ollama run <model> "prompt"` 在 Slurm batch 裡整個卡住,直到 time limit 到期 **現象**:server log 顯示模型已經完全載入完成(`llama runner started in X seconds`),但之後完全沒有任何新的 log,永遠不會出現 `POST "/api/generate"` 這一行,job 就這樣一直耗到 `--time` 到期被強制砍掉。 **原因**:這是 Ollama CLI 已知、長年存在的行為問題——`ollama run <model> "prompt"` 這種把 prompt 當命令列參數傳入的用法,在非互動、沒有 TTY 的環境(例如 Slurm batch job)下,實測會卡在送出真正推論請求之前,不會拋出任何錯誤訊息,只是單純不動作。加 `< /dev/null` 明確關閉 stdin 不足以解決這個問題。 **解法**:改用 pipe 方式餵入 prompt,而不是當命令列參數。 ```bash # 容易卡住 $ollama_bin run llama3.2:1b "請用一句話自我介紹" # 改用這個寫法 echo "請用一句話自我介紹" | $ollama_bin run llama3.2:1b ``` ## 問題 4:用 `ollama run` 後推論明顯很慢 **根因**:Ollama 可能會偵測到整個節點的實體核心數,開出遠超過 `--cpus-per-task` 實際分配到的執行緒,執行緒互相搶核心、頻繁 context switch,反而拖慢速度。可在 server log 的 `load request` 那行確認: ``` msg=load request="{... NumThreads:112 ...}" ``` 若這個數字遠大於 job script 裡的 `--cpus-per-task`,就是這個問題。 **解法**:`ollama run` 不支援直接在指令列加 `num_thread` 參數,改用 Modelfile 建立內建這個參數的衍生模型,詳見 Step 3 的說明。 <br> <!-- 作者資訊 --> <div style="border-top: 2px solid #eee; padding: 28px 20px; display: flex; justify-content: space-between; align-items: center; font-family: sans-serif;"> <div> <div style="font-size: 20px; font-weight: bold; margin-bottom: 8px;"> 在 HPC 系統上透過 Slurm 部署 Ollama</div> <div style="max-width: 640px; color: #444; line-height: ;"> Author:Guan-Lin, Chen <br>Date:2026-08-07</div> </div> <div> <a href="https://man.twcc.ai/@f1-manual/manual" target="_blank" style="display: inline-block;"> <img src=" https://iservice.nchc.org.tw/nchc_service/images/nchc/pi4.png" alt="創進一號使用說明" style="height: 80px;"> </a> </div> </div>

Import from clipboard

Advanced permission required

Your current role can only read. Ask the system administrator to acquire write and comment permission.

This team is disabled

Sorry, this team is disabled. You can't edit this note.

This note is locked

Sorry, only owner can edit this note.

Reach the limit

Sorry, you've reached the max length this note can be.
Please reduce the content or divide it to more notes, thank you!

Import from Gist

Import from Snippet

or

Export to Snippet

Are you sure?

Do you really want to delete this note?
All users will lost their connection.

Create a note from template

Create a note from template

Oops...
This template has been removed or transferred.


Upgrade

All
  • All
  • Team
No template.

Create a template


Upgrade

Delete template

Do you really want to delete this template?

This page need refresh

You have an incompatible client version.
Refresh to update.
New version available!
See releases notes here
Refresh to enjoy new features.
Your user state has changed.
Refresh to load new user state.

Sign in

Sign in via SAML

Help

  • English
  • 中文
  • 日本語

Documents

Tutorials

Book Mode Tutorial

Slide Example

YAML Metadata

Resources

Releases

Blog

Policy

Terms

Privacy

Cheatsheet

Syntax Example Reference
# Header Header 基本排版
- Unordered List
  • Unordered List
1. Ordered List
  1. Ordered List
- [ ] Todo List
  • Todo List
> Blockquote
Blockquote
**Bold font** Bold font
*Italics font* Italics font
~~Strikethrough~~ Strikethrough
19^th^ 19th
H~2~O H2O
++Inserted text++ Inserted text
==Marked text== Marked text
[link text](https:// "title") Link
![image alt](https:// "title") Image
`Code` Code 在筆記中貼入程式碼
```javascript
var i = 0;
```
var i = 0;
:smile: :smile: Emoji list
{%youtube youtube_id %} Externals
$L^aT_eX$ LaTeX
:::info
This is a alert area.
:::

This is a alert area.

Versions

Versions and GitLab Sync

Sign in to link this note to GitLab Learn more
This note is not linked with GitLab Learn more
 
Add badge Pull Push GitLab Link Settings
Upgrade now

Version named by    

More Less
  • Edit
  • Delete

Note content is identical to the latest version.
Compare with
    Choose a version
    No search result
    Version not found

Feedback

Submission failed, please try again

Thanks for your support.

On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

Please give us some advice and help us improve HackMD.

 

Thanks for your feedback

Remove version name

Do you want to remove this version name and description?

Transfer ownership

Transfer to
    Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

      Link with GitLab

      Please authorize HackMD on GitLab

      Please sign in to GitLab and authorize HackMD to access your projects. Learn more

       Sign in to GitLab

      Push the note to GitLab Push to GitLab Pull a file from GitLab

        Authorize again
       

      Choose which file to push to

      Select repo
      Refresh
      Select branch
      Select file
      Select branch
      Choose version(s) to push
      • Save a new version and push
      • Choose from existing versions
      Available push count

      Upgrade

      Pull from GitLab

       
      File from GitLab
      File from HackMD

      GitLab Link Settings

      File linked

      Linked by
      File path
      Last synced branch
      Available push count

      Upgrade

      Danger Zone

      Unlink
      You will no longer receive notification when GitLab file changes after unlink.

      Syncing

      Push failed

      Push successfully