CUDA 流式消毒器¶
注意
這是一個原型功能,表示它處於早期階段,供回饋和測試,其組成部分可能會有所變更。
概覽¶
此模組介紹 CUDA 消毒器,這是一種用於偵測在不同串流上執行的核心之間的同步錯誤的工具。
它會儲存張量的存取資訊,以判斷它們是否已同步。當在 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)
再次執行腳本時,不會報告任何錯誤。