評價此頁

CUDA 流消毒器#

創建於: 2022 年 09 月 09 日 | 最後更新於: 2022 年 10 月 31 日

注意

這是一個原型功能,意味著它處於早期階段,供反饋和測試,並且其元件可能會發生變化。

概述#

此模組介紹了 CUDA Sanitizer,一個用於檢測在不同流上執行的核心之間的同步錯誤的工具。

它儲存關於張量訪問的資訊,以確定它們是否已同步。當在 Python 程式中啟用並透過檢測到可能的資料競爭時,會列印詳細的警告並退出程式。

可以透過匯入此模組並呼叫 enable_cuda_sanitizer() 或匯出 TORCH_CUDA_SANITIZER 環境變數來啟用它。

用法#

以下是一個 PyTorch 中簡單同步錯誤的示例

import torch

a = torch.rand(4, 2, device="cuda")

with torch.cuda.stream(torch.cuda.Stream()):
    torch.mul(a, 5, out=a)

張量 `a` 在預設流上初始化,並且在沒有同步方法的情況下,在一個新流上被修改。這兩個核心將在同一張量上併發執行,這可能導致第二個核心在第一個核心能夠寫入之前讀取未初始化的資料,或者第一個核心可能會覆蓋第二個核心的一部分結果。當在命令列上執行此指令碼時,使用

TORCH_CUDA_SANITIZER=1 python example_error.py

CSAN 會列印以下輸出

============================
CSAN detected a possible data race on tensor with data pointer 139719969079296
Access by stream 94646435460352 during kernel:
aten::mul.out(Tensor self, Tensor other, *, Tensor(a!) out) -> Tensor(a!)
writing to argument(s) self, out, and to the output
With stack trace:
  File "example_error.py", line 6, in <module>
    torch.mul(a, 5, out=a)
  ...
  File "pytorch/torch/cuda/_sanitizer.py", line 364, in _handle_kernel_launch
    stack_trace = traceback.StackSummary.extract(

Previous access by stream 0 during kernel:
aten::rand(int[] size, *, int? dtype=None, Device? device=None) -> Tensor
writing to the output
With stack trace:
  File "example_error.py", line 3, in <module>
    a = torch.rand(10000, device="cuda")
  ...
  File "pytorch/torch/cuda/_sanitizer.py", line 364, in _handle_kernel_launch
    stack_trace = traceback.StackSummary.extract(

Tensor was allocated with stack trace:
  File "example_error.py", line 3, in <module>
    a = torch.rand(10000, device="cuda")
  ...
  File "pytorch/torch/cuda/_sanitizer.py", line 420, in _handle_memory_allocation
    traceback.StackSummary.extract(

這提供了對錯誤的起源的廣泛洞察

  • 張量來自 ID 為:0(預設流)和 94646435460352(新流)的流不正確地訪問

  • 該張量是透過呼叫 a = torch.rand(10000, device="cuda") 分配的

  • 錯誤的訪問是由以下運算元引起的
    • a = torch.rand(10000, device="cuda") 在流 0 上

    • torch.mul(a, 5, out=a) 在流 94646435460352 上

  • 錯誤訊息還顯示了呼叫運算元的模式,並附帶一個說明運算元的哪些引數對應於受影響張量的註釋。

    • 在示例中,可以看到張量 `a` 對應於運算元 torch.mul 的引數 `self`、`out` 以及 `output` 值。

另請參閱

支援的 torch 運算元及其模式的列表可以在 這裡 檢視。

透過強制新流等待預設流來修復錯誤

with torch.cuda.stream(torch.cuda.Stream()):
    torch.cuda.current_stream().wait_stream(torch.cuda.default_stream())
    torch.mul(a, 5, out=a)

當指令碼再次執行時,沒有報告任何錯誤。

API 參考#

torch.cuda._sanitizer.enable_cuda_sanitizer()[源]#

啟用 CUDA Sanitizer。

消毒器將開始分析 torch 函式呼叫的低階 CUDA 呼叫是否存在同步錯誤。所有找到的資料競爭都將列印到標準錯誤輸出,以及可疑原因的堆疊跟蹤。為了獲得最佳結果,應在程式的最開始啟用消毒器。