评价此页

CUDA 流消毒器#

创建日期:2022年9月9日 | 最后更新日期:2022年10月31日

注意

这是一个原型功能,意味着它仍处于早期阶段,旨在收集反馈和进行测试,其组件可能会有所变动。

概述#

本模块引入了 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 在默认流上初始化,且在没有任何同步方法的情况下,在另一个新流上被修改。这两个内核将在同一个张量上并发运行,这可能导致第二个内核在第一个内核写入数据之前读取到未初始化的数据,或者第一个内核可能覆盖了第二个内核部分的结果。当在命令行运行此脚本时

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") 分配的

  • 错误访问是由以下运算符引起的
    • 流 0 上的 a = torch.rand(10000, device="cuda")

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

  • 错误消息还显示了所调用运算符的模式 (schemas),以及显示运算符的哪些参数对应于受影响张量的说明。

    • 在该示例中,可以看到张量 a 对应于所调用运算符 torch.mulselfout 参数以及 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]#

启用 CUDA 消毒器。

消毒器将开始分析由 torch 函数调用的底层 CUDA 调用,以查找同步错误。发现的所有数据竞争都将与可疑原因的堆栈跟踪一起打印到标准错误输出中。为获得最佳结果,应在程序的最开始处启用消毒器。