捷徑

疑難排解

請注意,本節中的資訊可能會在未來版本的 *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 區域

  1. 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 上開啟功能要求。

清除指標報告

如果您想要清除步驟/epochs 之間的指標,您可以使用

import torch_xla.debug.metrics as met

met.clear_all()

PyTorch/XLA + Dynamo 偵錯工具

您可以透過設定 XLA_DYNAMO_DEBUG=1 來啟用 PyTorch/XLA + Dynamo 偵錯工具。

效能分析

為了深入分析您的工作負載以了解瓶頸,請查看以下資源

簡單基準測試

請參考

examples/debug/train_resnet_benchmark.py,了解如何基準測試 PyTorch/XLA 模型。

已知的效能注意事項

PyTorch/XLA 在語意上與一般 PyTorch 相似,而 XLA 張量與 CPU 和 GPU 張量共享完整的張量介面。然而,XLA/硬體中的限制和延遲評估模型表示某些模式可能會導致不良的效能。

如果您的模型顯示效能不佳,請記住以下注意事項

  1. 過多的重新編譯會導致 XLA/TPU 效能降低。

    XLA 編譯非常耗費資源。每次遇到新的形狀時,PyTorch/XLA 都會自動重新編譯圖形。通常模型會在幾個步驟內穩定下來,您可以在剩餘的訓練中看到巨大的加速。

    為了避免重新編譯,不僅形狀必須恆定,所有主機中 XLA 裝置之間的計算也應恆定。

    可能的來源:

    • 直接或間接使用 nonzero 會引入動態形狀;例如,遮罩索引 base[index],其中 index 是遮罩張量。

    • 步驟之間具有不同迭代次數的迴圈可能會導致不同的執行圖形,因此需要重新編譯。

    解決方案:

    • 張量形狀在迭代之間應相同,或應使用少量的形狀變化。

    • 盡可能將張量填充到固定大小。

  2. 某些運算沒有對 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)))
      
  3. torch_xla.distributed.data_parallel 中的迭代器可能會捨棄輸入迭代器中的最後幾個批次。

    這是為了確保我們在所有 XLA 裝置上執行相同的工作量。

    解決方案:

    • 當資料集很小時,並且步驟太少時,這可能會導致無運算 (no-op) epoch。因此,在這些情況下,最好使用小批次大小。

XLA 張量特性

  1. **XLA 張量內部結構是不透明的。** XLA 張量始終顯示為連續且沒有儲存空間。網路不應嘗試檢查 XLA 張量的步幅。

  2. **XLA 張量應在儲存之前移動到 CPU。** 直接儲存 XLA 張量會導致它們被載回儲存它們的裝置。如果裝置在載入時不可用,則載入將會失敗。將 XLA 張量在儲存之前移動到 CPU 可讓您決定將載入的張量放在哪些裝置上。如果您想要在沒有 XLA 裝置的機器上載入張量,這是必要的。但是,在儲存 XLA 張量之前將它們移動到 CPU 時應謹慎,因為跨裝置類型移動張量不會保留視圖關係。相反地,應在載入張量後根據需要重建視圖。

  3. **使用 Python 的 copy.copy 複製 XLA 張量會傳回深層複製,而不是淺層複製。** 使用 XLA 張量的視圖來取得它的淺層複製。

  4. **處理共享權重。** 模組可以透過將一個模組的參數設定為另一個模組來共享權重。模組權重的這種「綁定」應在模組移動到 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/XLA TF_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

應該可行。

文件

存取 PyTorch 的全面開發者文件

查看文件

教學

為初學者和進階開發者取得深入的教學

查看教學

資源

尋找開發資源並獲得解答

查看資源