CUDA 流检查器¶
注意
这是一个原型功能,这意味着它处于早期阶段,用于反馈和测试,其组件可能随时更改。
概述 ¶
本模块介绍了 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
索引的 tensor 在默认流上初始化,并且在没有任何同步方法的情况下,在新的流上进行了修改。这两个内核将在同一张 tensor 上并发运行,这可能会导致第二个内核在第一个内核有机会写入之前读取未初始化的数据,或者第一个内核可能会覆盖第二个内核的部分结果。当在命令行上运行此脚本时:
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()[source][source]
启用 CUDA 检查器。
检查器将开始分析由 torch 函数调用的低级 CUDA 调用中的同步错误。所有发现的数据竞争将被打印到标准错误输出,并附带疑似原因的堆栈跟踪。为了获得最佳结果,应在程序开始时启用检查器。