:::

NVIDIA Jetson AGX Thor ・ 技術文件

研華 MIC-743 優化設定

NVIDIA Jetson AGX Thor 從開箱到可交付:效能、環境、網路的完整設定與驗收流程。適用 L4T R39 Rev 2.0(JetPack 7.2)。文件版本 v2.2,2026 年 9 月 2 日,云碩科技股份有限公司。

研華 MIC-743-AT 卡通示意圖 研華 MIC-743-AT 卡通示意圖
適用機型NVIDIA Jetson AGX Thor 平台(Developer Kit 與工業型機箱同適用)
BSP 版本L4T R39 Rev 2.0(JetPack 7.2)
搭配交換機L3 網管交換機(支援 100G QSFP28 拆分為 4×25G,具 NX-OS 或同等網路作業系統)
文件版本v2.2(對外版)
建立日期2026-09-02
維護單位云碩科技股份有限公司
01

本文件的用途

這份指南寫給第一次接手 Thor 設備的工程師。目標是把一台剛開箱、或剛重新燒錄完 BSP 的 Thor,設定到可以交付的狀態。

每一章都是「為什麼要做、怎麼做、怎麼驗證」三段。所有指令都在 節點A 與 節點B 兩台實機、以及 L3 網管交換機上實際執行並驗證過,不是照抄官方文件。第九章的踩坑紀錄每一條都是真的踩過才寫進來的,建議先掃一遍再動手。

設定順序有相依性,請由第三章往後依序執行。

實測效能

項目數值
10G 單流吞吐量7.48 Gbits/sec
10G 四流吞吐量8.92 Gbits/sec
32 條並行連線7.30 Gbits/sec
小封包(512 bytes)3.41 Gbits/sec
延遲0.69 ms
滿載時 CPU 閒置率92%

回到目錄

02

設定順序總覽

從零到可交付共七個階段。每個階段都要驗證通過再進下一個。

階段項目為什麼要做需重開機
1主機名與時區多台同名無法辨識;UTC 時間讓 log 判讀困難
2電源模式 MAXN出廠預設是 120W,GPU 被限制在 1386 MHz
3鎖定時脈MAXN 只放開上限,實際頻率仍會浮動
4CUDA 與 Docker開發與部署的基礎環境
5交換機拆分設定10G 埠預設是單一 100G,與 Thor 談不攏
6Thor 網路設定10G 埠預設不會自己啟用
7驗收檢查確認前六項都生效且能跨重開機

回到目錄

03

階段一:主機名與時區

3.1 主機名

Thor 出廠的主機名一律是 ubuntu。同時管理兩台以上時,SSH 進去完全分不出是哪一台,這在遠端操作時很容易改錯機器。

sudo hostnamectl set-hostname 節點A
sudo sed -i "s/\bubuntu\b/節點A/g" /etc/hosts

第二行不能省。只改 hostnamectl 而沒有同步 /etc/hosts 的話,127.0.1.1 仍指向舊名稱,部分程式在解析自己的主機名時會逾時。

驗證:

hostnamectl --static
grep 127 /etc/hosts

3.2 時區

出廠預設是 Etc/UTC。台灣現場使用時,所有 log、journalctl、訓練進度的時間戳都要自己加八小時,很容易看錯。

sudo timedatectl set-timezone Asia/Taipei

驗證應顯示 Asia/Taipei (CST, +0800)

timedatectl | grep -E "Local time|Time zone"

回到目錄

04

階段二:電源模式設為 MAXN

4.1 為什麼

Thor 的 nvpmodel 有四個模式。出廠預設是 ID 1(120W),不是最高效能:

模式 ID名稱GPU 上限NVDEC 上限CPU 上限
0MAXN1575 MHz1692 MHz2601 MHz
1120W(出廠預設)1386 MHz1557 MHz2601 MHz
290W較低較低較低
370W最低最低最低

CPU 上限在 MAXN 與 120W 之間沒有差別,差的是 GPU 與影像解碼單元,GPU 相差約 12%。跑推論或影像管線時這個差距會直接反映在吞吐量上。

4.2 設定與持久化(兩個地方都要改)

這是最容易做半套的地方。nvpmodel -m 0 只寫入執行期狀態檔 /var/lib/nvpmodel/status,開機時由 nvpmodel.service 讀取。但如果那支檔被清除、或系統做過還原,就會退回設定檔裡的 PM_CONFIG DEFAULT,而出廠值是 1。

sudo nvpmodel -m 0
sudo cp -a /etc/nvpmodel/nvpmodel_p3834_0008.conf /etc/nvpmodel/nvpmodel_p3834_0008.conf.bak
sudo sed -i "s/^< PM_CONFIG DEFAULT=1 >/< PM_CONFIG DEFAULT=0 >/" /etc/nvpmodel/nvpmodel_p3834_0008.conf

設定檔名稱依板型而異,Thor Developer Kit 是 nvpmodel_p3834_0008.conf,實際檔名可用 readlink -f /etc/nvpmodel.conf 確認。

4.3 驗證

nvpmodel -q
cat /var/lib/nvpmodel/status
grep "^< PM_CONFIG" /etc/nvpmodel/nvpmodel_p3834_0008.conf

三者應分別顯示 MAXN / pmode:0000 / DEFAULT=0

回到目錄

05

階段三:鎖定時脈

5.1 為什麼

nvpmodel 決定的是頻率上限。實際運作時 CPU governor 仍是 schedutil,會依負載動態調頻,GPU 也會在閒置時降頻。做效能量測、或需要穩定延遲的即時應用時,這種浮動會造成數據不可重現。

jetson_clocks 的作用是把 CPU、GPU、EMC 的最小頻率拉到等於最大頻率,等於鎖死在上限。

5.2 關鍵前提

jetson_clocks 必須在 nvpmodel 之後執行。順序顛倒的話會鎖到舊模式的上限,得到一台「顯示 MAXN 但實際跑 120W 頻率」的機器,而且很難察覺。

5.3 先保存原始設定

jetson_clocks 不會自己記得原本的值。要能還原,必須在第一次鎖頻之前先存檔:

sudo jetson_clocks --store /etc/l4t_dfs.conf

這一步只能做一次。已經鎖頻後再執行,存下來的就是鎖頻後的狀態,還原功能等於失效。

5.4 建立開機服務

jetson_clocks 的效果不會跨重開機,必須做成 systemd 服務。建立 /etc/systemd/system/jetson-clocks.service

[Unit]
Description=Lock Jetson clocks to max frequency (jetson_clocks)
After=nvpmodel.service
Wants=nvpmodel.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStartPre=/bin/sleep 20
ExecStart=/usr/bin/jetson_clocks
ExecStop=/usr/bin/jetson_clocks --restore /etc/l4t_dfs.conf
[Install]
WantedBy=multi-user.target

三個欄位的用意:

After=nvpmodel.service 保證排序正確,這是 5.2 節的要求。

ExecStartPre=/bin/sleep 20 是緩衝。nvpmodel 是 oneshot 服務,systemd 認定它完成之後,SoC 端仍需要數秒才會穩定套用新的電源模式。沒有這段等待時,偶發會鎖到過渡狀態的頻率。

RemainAfterExit=yes 讓 oneshot 服務執行完仍保持 active 狀態,這樣 systemctl stop 才會觸發 ExecStop 的還原動作。

啟用:

sudo systemctl daemon-reload
sudo systemctl enable jetson-clocks.service
sudo jetson_clocks

5.5 驗證

鎖定成功的判準是 MinFreq 等於 MaxFreq:

sudo jetson_clocks --show | grep -E "^cpu0:|gpu-gpc-0|^EMC"
cpu0:      MinFreq=2601000     MaxFreq=2601000
gpu-gpc-0  MinFreq=1575000000  MaxFreq=1575000000
EMC        MinFreq=4266000000  MaxFreq=4266000000

GPU 若停在 1386000000,代表 nvpmodel 沒生效或順序錯了,回頭檢查第四章。

5.6 散熱注意事項

鎖頻後系統會持續維持高頻,待機功耗與發熱都明顯上升。Thor 的風扇由 nvfancontrol 服務以 close_loop 模式自動調節,預設 cool 曲線,正常散熱環境下不需人工介入。但機殼進出風口必須淨空,且應定期確認溫度:

paste <(cat /sys/class/thermal/thermal_zone*/type) <(cat /sys/class/thermal/thermal_zone*/temp)

數值單位為千分之一度,48250 即 48.25 度。閒置時約 45 至 50 度屬正常。

要暫時解除鎖頻:sudo systemctl stop jetson-clocks.service

回到目錄

06

階段四:CUDA 與 Docker

6.1 CUDA:不要安裝 nvidia-jetpack 整包

這是本次最大的軟體坑。直覺會執行 sudo apt install nvidia-jetpack,但在 R39 Rev 2.0 上會直接失敗:

The following packages have unmet dependencies:
nvidia-l4t-kernel-openrm : Depends: nvidia-l4t-init-openrm but it is not going to be installed
nvidia-l4t-kernel-partitions : Depends: nvidia-l4t-bootloader-utils but it is not going to be installed

原因是 nvidia-jetpack 這個 meta 套件會連 kernel 與 bootloader 套件一起拉,與已經燒錄在裝置上的 BSP 版本衝突。

正確做法是只裝需要的 CUDA 工具鏈:

sudo apt update
sudo apt install -y cuda-toolkit-13-2

BSP 本身已內含 GPU 驅動與 L4T 執行期(約 59 個 nvidia 套件),缺的只有開發工具鏈。

nvcc 預設不在 PATH 中,建立 /etc/profile.d/cuda.sh

export PATH=/usr/local/cuda/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH

6.2 Docker:用官方來源,不要用 docker.io

Ubuntu 內建的 docker.io 版本較舊,且與 NVIDIA Container Toolkit 的搭配較不穩定。使用 Docker 官方 apt 來源:

sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=arm64 signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu noble stable" | sudo tee /etc/apt/sources.list.d/docker.list
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

注意 arch=arm64。Thor 是 aarch64 架構,寫成 amd64 會找不到套件。

6.3 NVIDIA Container Toolkit

沒有這一步,容器內看不到 GPU。

sudo apt install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
sudo usermod -aG docker $USER

加入 docker 群組需要重新登入才會生效。

6.4 驗證

docker info | grep -iE "Runtimes|Default Runtime"

Runtimes 那一行必須看到 nvidia,否則容器拿不到 GPU。

回到目錄

07

階段五:交換機拆分設定

7.1 為什麼一定要做

Thor 的 QSFP 連接器不是一個 40G 或 100G 埠,而是四條各自獨立的 10GbE。這寫死在 device tree 裡:

ethernet@a808a10000  if-name=mgbe0_0  instance=0  uphy-gbe-mode=1  fixed-link speed=10000
ethernet@a808b10000  if-name=mgbe1_0  instance=1  uphy-gbe-mode=1  fixed-link speed=10000
ethernet@a808d10000  if-name=mgbe2_0  instance=2  uphy-gbe-mode=1  fixed-link speed=10000
ethernet@a808e10000  if-name=mgbe3_0  instance=3  uphy-gbe-mode=1  fixed-link speed=10000

四個介面的 MAC 位址是連號的(例如 3c:6d:66:e4:3b:d7da),代表它們共用同一顆實體連接器的四條 lane。

Thor 沒有 40G 或 100G 模式可選,也不能靠軟體改。因此對端交換機埠必須拆分成 4×10G,否則一邊講 100G、一邊講 4×10G,模組讀得到但協商不出可用速率,兩端都會顯示 Down。

7.2 確認交換機支援

show interface Ethernet1/49 capabilities

必須看到這兩行:

Speed: 1000,10000,25000,40000,50000,100000
Breakout capable: yes

速率清單裡要有 10000。另外注意 Port Group Members 這一欄,如果同一組內有多個埠,拆分時可能會互相影響。

7.3 套用拆分

configure terminal
interface breakout module 1 port 49-50 map 10g-4x
end
copy running-config startup-config

這是全域組態指令,不是進到 interface 底下打的,這點很常搞錯。

套用後埠會變成 Eth1/49/1Eth1/49/4Eth1/50/1Eth1/50/4,共八個 10G 子介面。原本 Eth1/49、Eth1/50 上的設定會被移除,必須重新套用到子介面上:

configure terminal
interface Ethernet1/49/1-4, Ethernet1/50/1-4
switchport
no shutdown
end
copy running-config startup-config

新建的子介面預設是 shutdown 且為 routed 模式,不下這段的話八個埠會停在 disabled。

7.4 驗證

show interface status | include 1/49|1/50
show running-config | include breakout

八個子介面應全部顯示 connected / full / 10G

要還原拆分:no interface breakout module 1 port 49-50 map 10g-4x

7.5 線材規格

Thor 端每條 lane 跑 10G NRZ。線材必須能承載四條 NRZ lane。

線材可用說明
40G QSFP+ 被動 DAC4 lane × 10G NRZ,規格完全吻合
100G QSFP28 被動 DAC4 lane × 25G NRZ,降速跑 10G 在電氣上沒問題
200G QSFP112 DAC不可4 lane × 50G PAM4,調變方式不同,無法降到 NRZ

本次實際使用並驗證可行的是 ONTi 的 ONT-DAC-QS28-1(1 公尺 QSFP28 被動銅纜),交換機讀到的 EEPROM 型號為 QSFP100G-4SFP25G-CU1M

第三方模組在多數交換機上預設會被擋,必要時開放:

configure terminal
service unsupported-transceiver

7.6 交換機介質要先確認

L3 網管交換機 的 Eth1/1-48 是 10GBASE-T(RJ45 銅線),不是 SFP+。

show module
Mod Ports  Module-Type                            Model
1   54     48x10GT + 6x40G/100G Ethernet Module   L3 網管交換機

48x10GT 的 T 代表 twisted copper。這表示無法使用「QSFP 轉 4×SFP+ 破線接到前 48 埠」這種常見做法,10G 光纖只能走 Eth1/49-54 那六個 QSFP 埠。採購線材前務必先用 show module 確認介質型別。

回到目錄

08

階段六:Thor 網路設定

8.1 介面對照與角色

介面速度角色預設狀態
enP2p1s01 GbE管理備援已設定,可用
mgbe0_0 至 mgbe3_010 GbE對外主要未啟用

8.2 10G 埠的重要特性

四個 10G 埠在 device tree 中被宣告為 fixed-link,這帶來三個必須理解的限制:

第一,沒有 PHY,也沒有 SFP 管理框架ethtool -m mgbe0_0 會回 Operation not supported,代表核心到光模組之間沒有 I2C 通道。系統看不到模組型號、看不到收光功率,也無法判斷模組是否插著。排查實體問題時軟體端幫不上忙,只能靠交換機端。交換機的 show interface transceiver details 可以補上這塊盲區。

第二,不做自動協商ethtool 顯示的 Auto-negotiation: on 在 fixed-link 模式下沒有實際意義,因為沒有 PHY 可以協商。

第三,ethtool 顯示的 Speed: 10000Mb/s 是 device tree 寫死的值,不是協商結果。看到 10000 不代表線路已通,要看 Link detected

8.3 檢查是否有人停用了介面

接手既有設備時務必先檢查這支檔:

cat /etc/NetworkManager/conf.d/99-unmanage-mgbe.conf

本次在 節點A 上發現此檔存在,內容將三個 10G 埠標為 NetworkManager 不管理:

[keyfile]
unmanaged-devices=interface-name:mgbe0_0;interface-name:mgbe2_0;interface-name:mgbe3_0

被列入的介面開機後連 admin up 都不會做,nmcli 顯示 unmanaged,且任何連線設定都無法套用,錯誤訊息也完全不會提到這支檔。要使用該埠必須先將它移出清單或整支刪除。

8.4 讓未插線的介面也能保留 IP

10G 埠未接上線材時 NetworkManager 會判定為 unavailable,不會套用 IP 設定。建立 /etc/NetworkManager/conf.d/10-mgbe-ignore-carrier.conf

[device-mgbe]
match-device=interface-name:mgbe*
ignore-carrier=yes

這樣 IP 會先掛上,線路一通即可使用,不必再登入機器操作。

8.5 本次採用的網路架構

10G 承載對外主要位址,1G 降為管理備援。兩者都在同一個 VLAN 1 與同一個 192.0.2.0/24

介面IP閘道route-metric
對外主要mgbe0_0(10G)192.0.2.11192.0.2.254100
管理備援enP2p1s0(1G)192.0.2.21192.0.2.254700

兩張網卡都設預設路由,靠 metric 決定優先序。 正常情況全部走 10G;10G 斷線時該路由自動消失,1G 的 metric 700 立刻接手,機器不會失聯也不需人工介入。此行為已實測驗證。

要留意的取捨是:10G 斷線時 192.0.2.11 這個位址會整個消失,因為它只存在於 10G 網卡上。機器本身靠 1G 保持連線,但任何以該位址定址的服務會中斷,需改連管理位址。

8.6 設定指令

sudo nmcli con add type ethernet ifname mgbe0_0 con-name mgbe0_0-10g \
ipv4.method manual \
ipv4.addresses 192.0.2.11/24 \
ipv4.gateway 192.0.2.254 \
ipv4.dns 8.8.8.8 \
ipv4.route-metric 100 \
ipv4.dad-timeout 0 \
ipv6.method disabled \
connection.autoconnect yes
sudo nmcli con mod "Wired connection 1" \
ipv4.addresses 192.0.2.21/24 \
ipv4.gateway 192.0.2.254 \
ipv4.route-metric 700

ipv6.method disabled 是刻意的。資料傳輸埠只走 IPv4,關閉 IPv6 可避免介面掛上不必要的 link-local 位址,也減少介面 up 時多餘的鄰居探詢封包干擾排查判讀。

8.7 搬移 IP 的順序至關重要

必須先讓 1G 放掉對外位址,10G 才拿得到。 順序顛倒會失敗:

Error: Connection activation failed: IP configuration could not be reserved

原因是 NetworkManager 的位址衝突偵測(ACD)會發現該位址仍在同一台機器的另一張網卡上。正確順序是:

  1. 兩個 profile 都先改設定,不啟用
  2. nmcli con up "Wired connection 1" 讓 1G 換到管理位址,釋放對外位址
  3. nmcli con up mgbe0_0-10g 讓 10G 接手
  4. 驗證通過再存檔

另外在 10G 的 profile 上設 ipv4.dad-timeout 0 關閉 ACD 探測,可避免殘留的 ARP 快取造成誤判。

強烈建議把整套動作寫成腳本,用 setsid nohup 脫離 SSH 執行,並內建回滾:套用後自動 ping 閘道驗證,若干秒內驗不過就自動還原。搬移 IP 的瞬間必然斷線,沒有回滾機制的話一旦出錯就要進機房接螢幕。本次第一輪就是靠這個機制自動還原,全程沒有失聯。

8.8 如何確認流量真的走 10G

這一節很重要,因為預設的測試方式會給出假的成功結果。

當 10G 埠與 1G 埠在同一網段時,即使 10G 完全沒有連線,從外部 ping 10G 的 IP 仍然會有回應,因為 Linux 預設會用任何一張可用介面回應本機所有 IP。

測試方式是否可信說明
ping <10G的IP>不可信由 1G 埠代為回應
ping -I <10G的IP> <目標>不可信綁的是 IP,核心仍會改走 1G
ping -I mgbe0_0 <目標>可信綁實體介面,強制由 10G 送出
檢查 rx_packets 增量最可信硬體計數器不會說謊

判斷連線狀態的唯一可靠依據:

cat /sys/class/net/mgbe0_0/carrier
ethtool -S mgbe0_0 | grep link_connect_count

carrier 回 1 代表實體層已連線。link_connect_count 是硬體計數器,只要曾經 link up 過一次就會累加,數值為 0 表示從未連線成功。

同網段測試的陷阱:兩台機器互相 ping 時,回程封包會依 route metric 選擇介面,可能從 1G 回來,而 ping -I 綁定的 socket 不會接受從其他介面進來的封包,導致明明線路正常卻顯示 100% 逾時。做效能或連通性驗證時,建議在 10G 上另外加一個獨立網段(例如 198.51.100.0/24)避開這個干擾。

8.9 疑難排解順序

10G 無法連線時,依此順序排查:

第一步,確認 NetworkManager 沒有停用該介面(8.3 節)。

第二步,在交換機上執行 show interface status,區分兩種 Reason:XCVR not inserted 是沒插線材,Link not connected 是插了、讀得到、但協商不起來。後者代表實體存在無虞,問題在設定或規格。

第三步,確認交換機埠已拆分為 4×10G(第七章)。這是最常見的原因。

第四步,用 show interface EthX/Y transceiver details 確認線材規格,特別是 PAM4 的 200G 線材無法用於 10G。

第五步,將兩台 Thor 以一條線直接對接。連線成功代表 Thor 與線材都正常,問題在交換機端;仍失敗則問題在模組或線材。這個測試能一次把範圍縮小一半,不需要交換機的管理權限。

回到目錄

09

MTU 與 MACsec

9.1 現況

四個 10G 埠的 MTU 預設是 1466,不是標準的 1500。開機訊息說明了原因:

nvethernet a808a10000.ethernet: Macsec: Reduced MTU: 1466 Max: 9000

MACsec(IEEE 802.1AE 鏈路層加密)在這些埠上是啟用的。它會在每個 frame 插入 SecTAG 與 ICV 完整性檢查碼,驅動為此保留 34 bytes。硬體與 device tree 的 nvidia,max-platform-mtu 都是 9000,但 MACsec 一開就被壓到 1466。

9.2 MACsec 是什麼、為什麼 Thor 預設開著

MACsec 保護的是「一條實體線路上兩個相鄰設備之間」的通訊,防的是有人在實體層接分光器或竊聽線路。它是逐跳加密而非端到端,封包進到交換機裡仍是明文,因此與 TLS、VPN 解決的是不同層次的問題。

典型使用場合是線路經過無法控制的實體空間:機房對機房的租用光纖、跨棟跨樓層的園區網路、電信商基地台回傳、金融專線。

Thor 上面有 MACsec 引擎的真正原因是它是車用平台。 車內 ECU 之間走 Automotive Ethernet,攻擊情境是有人拆開門板接進線束、注入假的感測器資料或控制指令,ISO/SAE 21434 這類車輛資安規範會要求車內網路做鏈路層加密。把車用晶片用於機房邊緣運算時,就繼承了這個為汽車設計的預設值。

9.3 在本專案環境中它並未實際運作

實測確認兩台機器都沒有任何 MACsec 工作階段:

ip macsec show                → 沒有任何 MACsec 介面
NM 連線類型                    → 802-3-ethernet(不是 macsec)
/etc/wpa_supplicant.conf      → 沒有任何 macsec 設定

系統上執行中的 wpa_supplicant 是 Ubuntu 預設實例,沒有帶 MKA 金鑰協商設定。

另外,交換機端也不支援:

show interface Ethernet1/49 capabilities
MACSEC capable: no

因此驅動保留了 34 bytes,給一個從未建立過工作階段、且對端也不支援的功能。

9.4 不改的實際影響(實測)

實測結果比預期溫和,不必急著處理。

情境實際影響嚴重度
容器內 TCPPMTUD 自動學習,路由快取記錄 mtu 1466,代價是首次一個 RTT(0.6 ms)可忽略
LLM 推論、RAG 查詢封包遠小於 1466,完全碰不到上限無影響
多人連線MTU 與連線數無關無影響
大檔傳輸吞吐量標頭佔比多約 2.3%可忽略
UDP 超過 1438 bytes靜默丟棄,不會自癒潛在風險
跨越會過濾 ICMP 的設備PMTUD 黑洞,小封包通、大檔卡死潛在風險

實測數據:容器(docker0 為 1500)對外送 1500 bytes DF 封包會被丟,但核心回的 ICMP 讓容器立即把 PMTU 學成 1466,路由快取顯示 cache expires 596sec mtu 1466。因為 ICMP 在同一台機器內部產生不會被過濾,此自癒機制可靠。

結論:改動的理由不是效能,而是消除未來的地雷。 非標準 MTU 會在加入 UDP 服務、流量跨越防火牆、或他人接手時炸出極難查的問題。不建議為此單獨安排停機,排到下次因其他原因重開機時順手處理即可。

9.5 關閉 MACsec 的方法(已在實機驗證)

編輯 /boot/extlinux/extlinux.conf,在 APPEND 行尾加入參數:

sudo cp -a /boot/extlinux/extlinux.conf /boot/extlinux/extlinux.conf.bak
sudo sed -i '/^ *APPEND .*root=PARTUUID/ s/$/ nvethernet.macsec_enable=0/' /boot/extlinux/extlinux.conf

重新開機後生效。這只是加一個模組參數而非更換核心,即使參數無效核心也只會忽略,不影響開機。

驗證五項:

cat /proc/cmdline | tr " " "\n" | grep nvethernet     # 應顯示 macsec_enable=0
cat /sys/module/nvethernet/parameters/macsec_enable   # 應為 N
journalctl -k -b | grep -i macsec                     # Reduced MTU 訊息應消失
cat /sys/class/net/mgbe0_0/mtu                        # 應為 1500

實測結果:MTU 自動從 1466 變為標準 1500,服務與既有 10G 鏈路完全不受影響。

9.6 Jumbo Frame

關閉 MACsec 後 MTU 上限解到 9000。實測可設定範圍:

設定值結果
1500成功
4000成功
9000成功
9216被拒(超過硬體上限)

Thor 的硬體上限是 9000,不是交換機慣用的 9216。 交換機端設 9216 沒問題(那是上限值),Thor 端只能設 9000。

要啟用 jumbo frame 必須全鏈路一致:Thor 兩端設 9000、交換機設 system jumbomtu 9216 並在八個子介面設 mtu 9216、Docker 設 9000。漏掉任何一環都會出現「小封包通、大檔卡住」的症狀,而且極難診斷。

9.7 若暫時不關 MACsec,Docker 需對齊

主機對外介面是 1466 但 docker0 與自訂 bridge 預設是 1500。雖然 TCP 會自行學習,仍建議在 /etc/docker/daemon.json 明確設定:

{ "mtu": 1466 }

既有的自訂 bridge 網路需重建才會套用新值。

回到目錄

10

階段七:驗收檢查表

重新開機後逐項執行。全部通過才算完成設定。

編號檢查項目指令預期結果
1主機名hostnamectl --static非 ubuntu,且各台不同
2時區timedatectl | grep "Time zone"Asia/Taipei (CST, +0800)
3電源模式nvpmodel -qMAXN
4模式持久化cat /var/lib/nvpmodel/statuspmode:0000
5設定檔預設值grep "^< PM_CONFIG" /etc/nvpmodel/nvpmodel_p3834_0008.confDEFAULT=0
6鎖頻服務systemctl is-enabled jetson-clocksenabled
7CPU 鎖頻jetson_clocks --show | grep ^cpu0:MinFreq 等於 MaxFreq(2601000)
8GPU 鎖頻jetson_clocks --show | grep gpu-gpc-0MinFreq 等於 MaxFreq(1575000000)
9還原檔存在ls -l /etc/l4t_dfs.conf檔案存在
10CUDA/usr/local/cuda/bin/nvcc --version顯示 13.2
11Dockerdocker --version29.7.2 或更新
12GPU 容器支援docker info | grep RuntimesRuntimes 含 nvidia
13交換機拆分show interface status | include 1/49八個子介面 connected / full / 10G
1410G 實體連線cat /sys/class/net/mgbe0_0/carrier1
1510G 曾連線ethtool -S mgbe0_0 | grep link_connect_count大於 0
16對外 IP 在 10G 上ip -4 -br addr show mgbe0_0顯示對外位址
17管理 IP 在 1G 上ip -4 -br addr show enP2p1s0顯示管理位址
18路由優先序ip route | grep ^default兩筆:mgbe0_0 metric 100、enP2p1s0 metric 700
19對外走 10Gip route get 8.8.8.8dev mgbe0_0
20故障切換關閉 10G 後測對外連線自動改走 enP2p1s0
21吞吐量iperf3 -c <對端> -P 4約 8.9 Gbits/sec
22溫度見 5.6 節閒置時低於 60 度

第 18 項要特別留意。若出現兩筆 metric 相同的預設路由,代表設定有誤,重開機後可能無法預期地選錯介面。

回到目錄

11

踩坑紀錄

以下每一項都是本次實際遇到並排除的問題。

  1. 一、nvpmodel -m 0 做半套。 只改執行期狀態而未改設定檔預設值,狀態檔一旦遺失就退回 120W,而且外觀上完全看不出來。兩個地方都要改。
  2. 二、jetson_clocksnvpmodel 之前執行。 會鎖到舊模式的上限,得到「顯示 MAXN 但實際跑較低頻率」的機器。systemd 服務必須加 After=nvpmodel.service
  3. 三、忘記先 --store 就鎖頻。 原始設定就此遺失,--restore 還原不回動態調頻,只能重新開機。
  4. 四、安裝 nvidia-jetpack 整包。 在 R39 Rev 2.0 上必定失敗於 kernel 與 bootloader 套件的相依性衝突。只裝 cuda-toolkit-13-2
  5. 五、Docker 來源寫成 amd64。 Thor 是 aarch64,必須指定 arch=arm64
  6. 六、以為 ping 得通就是 10G 通了。 同網段下 1G 埠會代為回應。務必用 ping -I <介面名> 並檢查 rx_packets 增量。
  7. 七、以為 ping -I <10G的IP> 逾時就是線路不通。 回程封包依 route metric 走了 1G,而綁定介面的 socket 不接受它,造成線路正常卻顯示 100% 逾時。應改用獨立網段測試,或直接看硬體計數器。
  8. 八、10G 埠設了與 1G 相同 metric 的預設閘道。 兩者競爭路由,可能導致設備失聯。應以 metric 明確區分優先序。
  9. 九、沒發現 99-unmanage-mgbe.conf 介面被 NetworkManager 排除後,任何設定都不會生效,且錯誤訊息完全不會提到這支檔。接手既有設備時必須先檢查。
  10. 十、搬移 IP 時順序顛倒。 先啟用 10G 去拿對外位址時,該位址仍在同一台機器的 1G 上,ACD 偵測到衝突而拒絕啟用。必須先讓 1G 換到管理位址釋放,10G 才拿得到。
  11. 十一、以為核心訊息 PCS block lock SUCCESS 代表已收到光訊號。 經對照實驗確認,該訊息來自驅動的 lane bring-up 流程,不能作為實體連線的判斷依據。唯一可信的是 carrierlink_connect_count
  12. 十二、用 200G QSFP112 線材接 10G 設備。 該規格每 lane 為 50G PAM4,與 Thor 的 10G NRZ 調變方式不同,無法降速使用。100G QSFP28(25G NRZ)則可正常降速。
  13. 十三、假設交換機的前 48 埠是 SFP+。 L3 網管交換機 是 48x10GT,全部為 RJ45 銅線埠,無法插光纖模組。採購線材前務必用 show module 確認介質。
  14. 十四、拆分後忘記重新套用介面設定。 breakout 會移除原埠的設定,新建的八個子介面預設是 shutdown 且為 routed 模式,必須手動補 switchportno shutdown
  15. 十五、Jumbo frame 設 9216。 Thor 硬體上限是 9000,9216 會被拒絕。交換機端可設 9216,Thor 端只能 9000。
  16. 十六、在介面 DOWN 的狀態下設定超出上限的 MTU。 指令會回報成功但實際值不變,自動化腳本會誤判為已完成。設定後必須讀回 /sys/class/net/<介面>/mtu 確認。
  17. 十七、把 ggml-rpc-server 綁在公網位址上。 RPC 協定沒有認證,等於對外開放無認證的遠端執行介面。必須在 10G 上另掛私有位址並只綁該位址。
  18. 十八、以為執行檔叫 rpc-server 實際檔名是 ggml-rpc-server,舊版文件與網路文章多寫成前者。
  19. 十九、以為模型檔要兩台各準備一份。 只有主控端需要 GGUF,權重會透過 RPC 推送到 worker。反過來說,載入時會有大量資料過網路,這正是需要 10G 的原因。
  20. 二十、手動指定 --tensor-split 50,50 兩台可用記憶體不同時會造成單邊 OOM。llama.cpp 依可用記憶體自動配比更可靠,不要手動干預。
  21. 二十一、沿用既有的 llama.cpp 建置。 預設 GGML_RPC:BOOL=OFF,不重新編譯無法使用 RPC。另外 Thor 出廠映像不含 cmake 與編譯工具鏈,白機需先安裝。

回到目錄

12

用 10G 串接兩台跑超大模型

本章內容已於 節點A 與 節點B 實機驗證完成,實際跑起 151 GB 的 DeepSeek-V4-Flash Q8,數據皆為實測值。

12.1 為什麼需要兩台

單台 Thor 的可用記憶體上限實測為 125,810 MiB(約 123 GB),由 ggml-rpc-server 啟動時回報。超過這個數字的模型單機放不下,必須跨機。

兩台合計約 245 GB,扣掉作業系統與其他服務,實務上約 200 GB 可用於模型權重。

12.2 只能用層切分,不能用張量切分

兩種平行化對網路的要求差了三個數量級:

方式每個 token 跨機傳輸量10G 夠不夠
層切分(pipeline parallel)只傳一份 hidden state綽綽有餘
張量切分(tensor parallel)每層都要 all-reduce 完整張量完全不夠

llama.cpp 的 RPC 模式採用的是層切分。以 hidden dimension 8192、fp16 估算,每個 token 跨機一次僅傳輸 16 KB,解碼階段 30 tokens/秒約需 3.8 Mbps,只佔 10G 頻寬的 0.04%

12.3 建置(預設未啟用 RPC)

兩台都必須重新編譯。節點B 原有的建置是 GGML_RPC:BOOL=OFF,不能直接用。

sudo apt install -y cmake build-essential git ccache
git clone --depth 1 https://github.com/ggml-org/llama.cpp.git
cd llama.cpp
export PATH=/usr/local/cuda/bin:$PATH
cmake -B build-rpc -DGGML_CUDA=ON -DGGML_RPC=ON \
-DCMAKE_BUILD_TYPE=Release -DCMAKE_CUDA_ARCHITECTURES=110
cmake --build build-rpc --config Release -j 12

CMAKE_CUDA_ARCHITECTURES=110 對應 Thor 的運算能力 11.0,可用 nvidia-smi --query-gpu=compute_cap --format=csv 確認。建議建置到獨立的 build-rpc/ 目錄,不影響既有的 build/

Thor 出廠映像不含 cmake 與編譯工具鏈,白機需先安裝。

12.4 安全性:RPC 絕對不可綁公網位址

ggml-rpc-server 啟動時會自行警告:

WARNING: Host is != '127.0.0.1'
Never expose the RPC server to an open network!
This is an experimental feature and is not secure!

RPC 協定沒有任何認證機制,允許遠端配置記憶體與執行運算。若 10G 網段承載的是可路由的公網位址公網位址,直接綁上去等於對外開放一個無認證的遠端執行介面。

正確做法是在 10G 介面上另外掛一組私有位址,RPC 只綁私有位址:

sudo nmcli con mod mgbe0_0-10g +ipv4.addresses 198.51.100.11/24
sudo nmcli con up mgbe0_0-10g

兩台分別使用 198.51.100.11198.51.100.12。這組位址已寫入 NetworkManager 設定,可跨重開機。設定後確認監聽位址:

ss -tlnp | grep 50052
LISTEN 198.51.100.12:50052

必須是私有位址,不可以是 0.0.0.0 或公網位址。

12.5 執行方式

執行檔名是 ggml-rpc-server,不是 rpc-server

在 worker 端啟動(此例為 節點B):

cd ~/llama.cpp/build-rpc/bin
./ggml-rpc-server -H 198.51.100.12 -p 50052 -c

-c 啟用本地檔案快取,避免每次載入都重新傳輸權重,強烈建議加上。

在主控端執行(此例為 節點A,模型檔放這裡):

cd ~/llama.cpp/build-rpc/bin
./llama-cli -m <模型第一個分片>.gguf \
--rpc 198.51.100.12:50052 \
-ngl 999 --no-mmap -c 4096 -n 64 --single-turn \
-p "你的提示詞"

多分片模型只需指定第一個分片,其餘會自動載入。

12.6 權重會透過網路傳輸

只有主控端需要模型檔。 主控端載入 GGUF 之後,透過 RPC 把該由遠端負責的張量推送過去,worker 端不需要有模型檔。

本次實測 151 GB 的模型中約有 67 GB 經 10G 傳到 節點B。以實測 8.9 Gbps 計算約需 60 秒。這是 10G 真正不可取代的地方——同樣的載入若走 1G 需要多花約 9 分鐘。

ggml-rpc-server -c 的本地快取可讓重複載入省去這段傳輸。

12.7 不要手動指定 tensor-split

llama.cpp 會依各裝置的可用記憶體自動配比,這比手動指定可靠。

本次實測時 節點B 有 14 個容器佔用 34 GB,可用記憶體只有 88 GB,而 節點A 有 118 GB。自動配比的結果是 91 GB / 67 GB,剛好避開 OOM。若照直覺手動設 --tensor-split 50,50(各 75 GB),節點B 會因記憶體不足而失敗。

12.8 實測數據

DeepSeek-V4-Flash-0731 UD-Q8_K_XL(151 GB,5 分片)跨兩台 Thor

項目數值
模型大小151 GB
載入時間約 6 分鐘(含磁碟讀取與 67 GB 網路傳輸)
Prompt 處理18.0 tokens/秒
文字生成10.7 tokens/秒
節點A 記憶體用量91 GB
節點B 記憶體用量101 GB(含既有容器 34 GB)

跨機開銷對照(Gemma-4-26B Q4,16 GB,此模型單機跑得動故可對照)

項目單機跨機差異
Prompt 處理153.9 t/s86.7 t/s−44%
文字生成52.5 t/s48.5 t/s−7.6%

生成速度只掉 7.6%,證實層切分對頻寬需求極低,主要成本是往返延遲(實測 0.69 ms)。Prompt 處理掉 44% 較多,因為預填階段要一次搬移大量 activation,且兩台是輪流工作而非同時運算。

12.9 可以跑多大的模型

模型量化後大小單機(123 GB)雙機(約 200 GB)
gpt-oss-120b MXFP459 GB不需要
Llama-70B Q870 GB不需要
DeepSeek-V4-Flash Q8151 GB不可已實測可行
Llama-405B Q4_K_M約 230 GB不可超出,需更低量化

單機放得下就不要拆。 層切分是兩台輪流工作而非同時運算,本質上是序列化的,一定比單機慢。只有在模型真的塞不進一台時才值得拆。

12.10 四條 lane 聚合的評估

目前只用了 mgbe0_0 一條 lane。四條可做 LACP 聚合(802.3ad),頻寬上看約 35 Gbps,交換機端八個子介面已具備條件。

對解碼階段沒有幫助(本來就只用 0.04% 頻寬),只會改善模型載入時的權重傳輸時間(本次約 60 秒,聚合後可降至約 20 秒)與長提示詞預填。以一次性成本換取多一層設定與故障點,除非要做分散式訓練的梯度同步,否則不建議。

回到目錄

13

附錄:可重複執行的腳本

thor-init.sh 涵蓋第三章至第六章的所有設定,可重複執行,已完成的項目會自動略過。

sudo bash thor-init.sh 節點A

test10g.sh 用於驗證流量是否真的走 10G,會顯示 carrier、綁定介面的 ping 結果、以及封包計數器增量。

./test10g.sh mgbe0_0 192.0.2.12

判準是 rx 增量必須大於 0,其他都可能是 1G 代為回應。

ipswap.sh 用於把對外位址從 1G 搬到 10G,內建順序控制與自動回滾。搬移 IP 必然會斷線,務必以 setsid nohup 脫離 SSH 執行。

回到目錄

需要整機交付

MIC-743-AT 由云碩依本指南設定完成後交付,含驗收清單

看 MIC-743-AT 產品頁與預約訂貨

本文所有指令皆於兩台實機與 L3 網管交換機實際執行驗證。技術問題來信 service@cloudinfo.com.tw。