疑難排解¶
請注意,本節中的資訊可能會在未來版本的 *PyTorch/XLA* 軟體中移除,因為其中許多資訊都是特定於給定的內部實作,而這些實作可能會變更。
健全性檢查¶
在執行任何深入的偵錯之前,我們想要對已安裝的 PyTorch/XLA 進行健全性檢查。
檢查 PyTorch/XLA 版本¶
PyTorch 和 PyTorch/XLA 版本應相符。請查看我們的 README 以取得更多關於可用版本的詳細資訊。
vm:~$ python
>>> import torch
>>> import torch_xla
>>> print(torch.__version__)
2.1.0+cu121
>>> print(torch_xla.__version__)
2.1.0
執行簡單計算¶
vm:~$ export PJRT_DEVICE=TPU
vm:~$ python3
>>> import torch
>>> import torch_xla.core.xla_model as xm
>>> t1 = torch.tensor(100, device=xm.xla_device())
>>> t2 = torch.tensor(200, device=xm.xla_device())
>>> print(t1 + t2)
tensor(300, device='xla:0')
使用虛假資料執行 Resnet¶
適用於 nightly 版本
vm:~$ git clone https://github.com/pytorch/xla.git
vm:~$ python xla/test/test_train_mp_imagenet.py --fake_data
對於發行版本 x.y
,您想要使用分支 rx.y
。例如,如果您安裝了 2.1 發行版本,您應該執行
vm:~$ git clone --branch r2.1 https://github.com/pytorch/xla.git
vm:~$ python xla/test/test_train_mp_imagenet.py --fake_data
如果您可以讓 resnet 執行,我們可以得出結論:torch_xla 已正確安裝。
效能偵錯¶
為了診斷效能問題,我們可以使用 *PyTorch/XLA* 提供的執行指標和計數器。當模型速度緩慢時,**第一件**要檢查的事情是產生指標報告。
指標報告對於診斷問題非常有幫助。如果您有的話,請嘗試將其包含在您發送給我們的錯誤報告中。
PyTorch/XLA 偵錯工具¶
您可以透過設定 PT_XLA_DEBUG_LEVEL=2
來啟用 PyTorch/XLA 偵錯工具,這會提供一些有用的偵錯功能。您也可以將偵錯等級降低至 1
以跳過執行分析。
執行自動指標分析¶
偵錯工具將分析指標報告並提供摘要。一些範例輸出將會是
pt-xla-profiler: CompileTime too frequent: 21 counts during 11 steps
pt-xla-profiler: TransferFromDeviceTime too frequent: 11 counts during 11 steps
pt-xla-profiler: Op(s) not lowered: aten::_ctc_loss, aten::_ctc_loss_backward, Please open a GitHub issue with the above op lowering requests.
pt-xla-profiler: CompileTime too frequent: 23 counts during 12 steps
pt-xla-profiler: TransferFromDeviceTime too frequent: 12 counts during 12 steps
編譯與執行分析¶
偵錯工具將分析您模型的每次編譯和執行。一些範例輸出將會是
Compilation Analysis: ================================================================================
Compilation Analysis: Compilation Cause
Compilation Analysis: mark_step in parallel loader at step end
Compilation Analysis: Graph Info:
Compilation Analysis: Graph Hash: c74c3b91b855b2b123f833b0d5f86943
Compilation Analysis: Number of Graph Inputs: 35
Compilation Analysis: Number of Graph Outputs: 107
Compilation Analysis: Python Frame Triggered Execution:
Compilation Analysis: mark_step (/workspaces/dk3/pytorch/xla/torch_xla/core/xla_model.py:1055)
Compilation Analysis: next (/workspaces/dk3/pytorch/xla/torch_xla/distributed/parallel_loader.py:44)
Compilation Analysis: __next__ (/workspaces/dk3/pytorch/xla/torch_xla/distributed/parallel_loader.py:32)
Compilation Analysis: train_loop_fn (/workspaces/dk3/pytorch/xla/examples/train_decoder_only_base.py:48)
Compilation Analysis: start_training (/workspaces/dk3/pytorch/xla/examples/train_decoder_only_base.py:65)
Compilation Analysis: <module> (/workspaces/dk3/pytorch/xla/examples/train_decoder_only_base.py:73)
Compilation Analysis: --------------------------------------------------------------------------------
Compilation Analysis: ================================================================================
Post Compilation Analysis: ================================================================================
Post Compilation Analysis: Graph input size: 1.548000 GB
Post Compilation Analysis: Graph output size: 7.922460 GB
Post Compilation Analysis: Aliased Input size: 1.547871 GB
Post Compilation Analysis: Intermediate tensor size: 12.124478 GB
Post Compilation Analysis: Compiled program size: 0.028210 GB
Post Compilation Analysis: --------------------------------------------------------------------------------
Post Compilation Analysis: ================================================================================
Execution Analysis: ================================================================================
Execution Analysis: Execution Cause
Execution Analysis: mark_step in parallel loader at step end
Execution Analysis: Graph Info:
Execution Analysis: Graph Hash: c74c3b91b855b2b123f833b0d5f86943
Execution Analysis: Number of Graph Inputs: 35
Execution Analysis: Number of Graph Outputs: 107
Execution Analysis: Python Frame Triggered Execution:
Execution Analysis: mark_step (/workspaces/dk3/pytorch/xla/torch_xla/core/xla_model.py:1055)
Execution Analysis: next (/workspaces/dk3/pytorch/xla/torch_xla/distributed/parallel_loader.py:44)
Execution Analysis: __next__ (/workspaces/dk3/pytorch/xla/torch_xla/distributed/parallel_loader.py:32)
Execution Analysis: train_loop_fn (/workspaces/dk3/pytorch/xla/examples/train_decoder_only_base.py:48)
Execution Analysis: start_training (/workspaces/dk3/pytorch/xla/examples/train_decoder_only_base.py:65)
Execution Analysis: <module> (/workspaces/dk3/pytorch/xla/examples/train_decoder_only_base.py:73)
Execution Analysis: --------------------------------------------------------------------------------
Execution Analysis: ================================================================================
編譯/執行的一些常見原因包括:1. 使用者手動呼叫 mark_step
。2. 平行載入器 每 x 個批次呼叫 mark_step
(可設定)。3. 退出 profiler StepTrace 區域。
Dynamo 決定編譯/執行圖形。5. 使用者嘗試在
mark_step
之前存取張量的值 (通常是因為記錄)。
由 1-4 引起的執行是預期的,我們想要避免 5,方法是減少存取張量值的頻率,或在存取之前手動新增 mark_step
。
使用者應該預期在前幾個步驟中看到 Compilation Cause
+ Executation Cause
配對。在模型穩定後,使用者應該預期只看到 Execution Cause
(您可以透過 PT_XLA_DEBUG_LEVEL=1
停用執行分析)。為了有效率地使用 PyTorch/XLA,我們期望每個步驟都執行相同的模型程式碼,並且每個圖形只發生一次編譯。如果您持續看到 Compilation Cause
,您應該嘗試依照 本節 傾印 IR/HLO,並比較每個步驟的圖形,以了解差異的來源。
以下章節將說明如何取得和理解更詳細的指標報告。
取得指標報告¶
將以下程式碼行放在您的程式中以產生報告
import torch_xla.debug.metrics as met
# For short report that only contains a few key metrics.
print(met.short_metrics_report())
# For full report that includes all metrics.
print(met.metrics_report())
理解指標報告¶
報告包含以下項目:- 我們發出 *XLA* 編譯的次數以及花費在發出上的時間。- 我們執行的次數以及花費在執行上的時間 - 我們建立/銷毀的裝置資料控制代碼數量等等。
此資訊以樣本百分位數的形式報告。一個範例是
Metric: CompileTime
TotalSamples: 202
Counter: 06m09s401ms746.001us
ValueRate: 778ms572.062us / second
Rate: 0.425201 / second
Percentiles: 1%=001ms32.778us; 5%=001ms61.283us; 10%=001ms79.236us; 20%=001ms110.973us; 50%=001ms228.773us; 80%=001ms339.183us; 90%=001ms434.305us; 95%=002ms921.063us; 99%=21s102ms853.173us
我們也提供計數器,它們是追蹤內部軟體狀態的具名整數變數。例如
Counter: CachedSyncTensors
Value: 395
在此報告中,任何以 aten::
開頭的計數器都表示 XLA 裝置和 CPU 之間的內容切換,這可能是模型程式碼中潛在的效能優化區域。
計數器可用於了解哪些運算被路由回 *PyTorch* 的 CPU 引擎。它們以其 C++ 命名空間完全限定
Counter: aten::nonzero
Value: 33
如果您看到 aten::
運算子,除了 nonzero
和 _local_scalar_dense
之外,通常表示 PyTorch/XLA 中缺少降低 (lowering)。請隨時在 GitHub issues 上開啟功能要求。
PyTorch/XLA + Dynamo 偵錯工具¶
您可以透過設定 XLA_DYNAMO_DEBUG=1
來啟用 PyTorch/XLA + Dynamo 偵錯工具。
已知的效能注意事項¶
PyTorch/XLA 在語意上與一般 PyTorch 相似,而 XLA 張量與 CPU 和 GPU 張量共享完整的張量介面。然而,XLA/硬體中的限制和延遲評估模型表示某些模式可能會導致不良的效能。
如果您的模型顯示效能不佳,請記住以下注意事項
過多的重新編譯會導致 XLA/TPU 效能降低。
XLA 編譯非常耗費資源。每次遇到新的形狀時,PyTorch/XLA 都會自動重新編譯圖形。通常模型會在幾個步驟內穩定下來,您可以在剩餘的訓練中看到巨大的加速。
為了避免重新編譯,不僅形狀必須恆定,所有主機中 XLA 裝置之間的計算也應恆定。
可能的來源:
直接或間接使用
nonzero
會引入動態形狀;例如,遮罩索引base[index]
,其中index
是遮罩張量。步驟之間具有不同迭代次數的迴圈可能會導致不同的執行圖形,因此需要重新編譯。
解決方案:
張量形狀在迭代之間應相同,或應使用少量的形狀變化。
盡可能將張量填充到固定大小。
某些運算沒有對 XLA 的原生轉換。
對於這些運算,PyTorch/XLA 會自動傳輸到 CPU 記憶體、在 CPU 上評估,並將結果傳輸回 XLA 裝置。在訓練步驟中執行過多此類運算可能會導致顯著的效能降低。
可能的來源:
item()
運算明確要求評估結果。除非必要,否則請勿使用它。
解決方案:
對於大多數運算,我們可以將它們降低 (lower) 到 XLA 來修正它。請查看 指標報告章節 以找出遺失的運算,並在 GitHub 上開啟功能要求。
即使 PyTorch 張量已知為純量,也請避免使用 tensor.item()。將其保留為張量,並對其使用張量運算。
在適用的情況下,使用
torch.where
來替代控制流程。例如,clip_grad_norm 中使用的帶有item()
的控制流程是有問題的,並且會影響效能,因此我們透過呼叫torch.where
修補 了clip_grad_norm_
,這為我們帶來了顯著的效能提升。... else: device = parameters[0].device total_norm = torch.zeros([], device=device if parameters else None) for p in parameters: param_norm = p.grad.data.norm(norm_type) ** norm_type total_norm.add_(param_norm) total_norm = (total_norm ** (1. / norm_type)) clip_coef = torch.tensor(max_norm, device=device) / (total_norm + 1e-6) for p in parameters: p.grad.data.mul_(torch.where(clip_coef < 1, clip_coef, torch.tensor(1., device=device)))
torch_xla.distributed.data_parallel
中的迭代器可能會捨棄輸入迭代器中的最後幾個批次。這是為了確保我們在所有 XLA 裝置上執行相同的工作量。
解決方案:
當資料集很小時,並且步驟太少時,這可能會導致無運算 (no-op) epoch。因此,在這些情況下,最好使用小批次大小。
XLA 張量特性¶
**XLA 張量內部結構是不透明的。** XLA 張量始終顯示為連續且沒有儲存空間。網路不應嘗試檢查 XLA 張量的步幅。
**XLA 張量應在儲存之前移動到 CPU。** 直接儲存 XLA 張量會導致它們被載回儲存它們的裝置。如果裝置在載入時不可用,則載入將會失敗。將 XLA 張量在儲存之前移動到 CPU 可讓您決定將載入的張量放在哪些裝置上。如果您想要在沒有 XLA 裝置的機器上載入張量,這是必要的。但是,在儲存 XLA 張量之前將它們移動到 CPU 時應謹慎,因為跨裝置類型移動張量不會保留視圖關係。相反地,應在載入張量後根據需要重建視圖。
**使用 Python 的 copy.copy 複製 XLA 張量會傳回深層複製,而不是淺層複製。** 使用 XLA 張量的視圖來取得它的淺層複製。
**處理共享權重。** 模組可以透過將一個模組的參數設定為另一個模組來共享權重。模組權重的這種「綁定」應在模組移動到 XLA 裝置**之後**完成。否則,共享張量的兩個獨立副本將會在 XLA 裝置上建立。
更多偵錯工具¶
我們不期望使用者使用本節中的工具來偵錯他們的模型。但是,當您提交錯誤報告時,我們可能會要求它們,因為它們提供了指標報告沒有的其他資訊。
print(torch_xla._XLAC._get_xla_tensors_text([res]))
,其中res
是結果張量,會印出 IR。print(torch_xla._XLAC._get_xla_tensors_hlo([res]))
,其中res
是結果張量,會印出產生的 XLA HLO。
請注意,這些函式必須在 mark_step()
之前呼叫,否則張量將已被實體化。
環境變數¶
還有許多環境變數可以控制 *PyTorch/XLA* 軟體堆疊的行為。
設定此類變數會導致不同程度的效能降低,因此它們應僅在偵錯時啟用。
XLA_IR_DEBUG
: 啟用在建立 IR 節點時擷取 *Python* 堆疊追蹤,因此允許了解哪個 *PyTorch* 運算負責產生 IR。XLA_HLO_DEBUG
: 啟用在XLA_IR_DEBUG
啟用時擷取的 *Python* 堆疊框架,以傳播到 *XLA* *HLO* 元資料。XLA_SAVE_TENSORS_FILE
: 用於傾印執行期間 IR 圖形的路徑。請注意,如果選項保持啟用狀態且 *PyTorch* 程式長時間執行,則檔案可能會變得非常大。圖形會附加到檔案,因此為了使每次執行都保持乾淨,應明確刪除該檔案。XLA_SAVE_TENSORS_FMT
: 儲存在XLA_SAVE_TENSORS_FILE
檔案中的圖形格式。可以是text
(預設)、dot
(*Graphviz* 格式) 或hlo
。XLA_FLAGS=--xla_dump_to
: 如果設定為=/tmp/dir_name
,XLA 編譯器將會傾印每個編譯的未優化和優化 HLO。XLA_METRICS_FILE
: 如果設定,則為本機檔案的路徑,內部指標將在每個步驟中儲存到該檔案。指標將附加到檔案 (如果已存在)。XLA_SAVE_HLO_FILE
: 如果設定,則為本機檔案的路徑,在發生編譯/執行錯誤時,有問題的 HLO 圖形將儲存到該檔案。XLA_SYNC_WAIT
: 強制 XLA 張量同步運算等待其完成,然後再移至下一步。XLA_USE_EAGER_DEBUG_MODE
: 強制 XLA 張量以 eager 模式執行,這表示逐一編譯和執行 torch 運算。這對於繞過長時間編譯很有用,但整體步驟時間會慢很多,並且記憶體使用量會更高,因為所有編譯器優化都將被跳過。TF_CPP_LOG_THREAD_ID
: 如果設定為 1,TF 日誌將顯示執行緒 ID,以協助偵錯多執行緒程序。TF_CPP_VMODULE
: 用於 TF VLOG 的環境變數,格式為TF_CPP_VMODULE=name=value,...
。請注意,對於 VLOG,您必須設定TF_CPP_MIN_LOG_LEVEL=0
。TF_CPP_MIN_LOG_LEVEL
: 要列印訊息的層級。TF_CPP_MIN_LOG_LEVEL=0
將開啟 INFO 記錄,TF_CPP_MIN_LOG_LEVEL=1
WARNING 等等。我們的 PyTorch/XLATF_VLOG
預設使用tensorflow::INFO
層級,因此要查看 VLOG,請設定TF_CPP_MIN_LOG_LEVEL=0
。XLA_DUMP_HLO_GRAPH
: 如果在發生編譯或執行錯誤時設定為=1
,則有問題的 HLO 圖形將會作為xla_util.cc
引發的執行階段錯誤的一部分傾印。
常見的偵錯環境變數組合¶
以 IR 格式記錄圖形執行
XLA_IR_DEBUG=1 XLA_HLO_DEBUG=1 XLA_SAVE_TENSORS_FMT="text" XLA_SAVE_TENSORS_FILE="/tmp/save1.ir"
以 HLO 格式記錄圖形執行
XLA_IR_DEBUG=1 XLA_HLO_DEBUG=1 XLA_SAVE_TENSORS_FMT="hlo" XLA_SAVE_TENSORS_FILE="/tmp/save1.hlo"
顯示執行階段和圖形編譯/執行的偵錯 VLOG
TF_CPP_MIN_LOG_LEVEL=0 TF_CPP_VMODULE="xla_graph_executor=5,pjrt_computation_client=3"
重現 PyTorch/XLA CI/CD 單元測試失敗。¶
您可能會看到 PR 的一些測試失敗,例如
若要執行此測試,請從基本 repo 目錄執行以下命令
PYTORCH_TEST_WITH_SLOW=1 python ../test/test_torch.py -k test_put_xla_uint8
直接在命令列中執行此操作無效。您需要將環境變數 TORCH_TEST_DEVICES
設定為您的本機 pytorch/xla/test/pytorch_test_base.py
。例如
TORCH_TEST_DEVICES=/path/to/pytorch/xla/test/pytorch_test_base.py PYTORCH_TEST_WITH_SLOW=1 python ../test/test_torch.py -k test_put_xla_uint8
應該可行。