Ray Compiled Graph 性能剖析指南:PyTorch Profiler、Nsight 与编译图可视化
2026/9/19 10:05:35 网站建设 项目流程

Ray Compiled Graph 性能剖析指南:PyTorch Profiler、Nsight 与编译图可视化

【免费下载链接】rayRay is an AI compute engine. Ray consists of a core distributed runtime and a set of AI Libraries for accelerating ML workloads.项目地址: https://gitcode.com/gh_mirrors/ra/ray

导读

Ray Compiled Graph(编译图,CGraph)是 Ray Core 面向 GPU 加速工作负载提供的高性能执行路径,它将一组跨 Actor 的 DAG 预先编译成确定性的调度与通信方案,从而降低每次执行时的任务级与系统级开销。本文以 doc/source/ray-core/compiled-graph/profiling.rst 为核心,完整讲解编译图的两种性能剖析方案——基于 PyTorch Profiler 的 Torch 追踪,以及基于 Nsight Systems + NVTX 的系统级剖析,并附带编译图结构的可视化方法。读完本文,你将能够:通过一行环境变量开启 Torch profiling 并产出每个 Actor 独立的 trace 文件;通过runtime_env为参与编译图的 Actor 挂载 Nsight 剖析并解读/tmp/ray/session_*/logs下的剖析结果;使用 NVTX 对执行循环中的方法调用做细粒度标注;最后用visualize()将编译后的图结构导出为 PNG 以便直观排查调度问题。

为什么需要剖析 Compiled Graph

编译图将 DAG 中每个 Actor 的方法调用与它们之间的数据传输(如 NCCL 张量传输通道)预编译为一份执行计划(schedule),由每个 Actor 内的执行循环按计划顺序执行。性能瓶颈往往来自两类开销:

  • 任务级开销:单个 task 从准备、反序列化到实际方法执行的耗时,以及多次执行之间的波动;
  • 系统级开销:调度、通信(如 NCCL 通道建立、张量传输)、内存拷贝等不属于用户计算代码的部分。

官方文档(即本主题来源文档)指出,Compiled Graph 提供基于 PyTorch 和基于 Nsight 两套剖析能力,目的是"更好地理解单个任务、系统开销与性能瓶颈",开发者可以按偏好任选其一。从源码看,这两套剖析均由环境变量开关控制,并在 Actor 的执行循环入口统一挂载,见 python/ray/dag/compiled_dag_node.py 中的do_exec_tasks实现。

PyTorch Profiler:一行环境变量开启 Torch 追踪

开启方式

PyTorch 剖析是成本最低的切入方式:运行脚本前设置环境变量RAY_CGRAPH_ENABLE_TORCH_PROFILING=1即可。例如对于编译图脚本example.py

RAY_CGRAPH_ENABLE_TORCH_PROFILING=1 python3 example.py

无需修改任何业务代码。从 python/ray/dag/constants.py 可以看到该开关的定义:

# Feature flag to turn on torch profiling. # This cannot be used together with RAY_CGRAPH_ENABLE_NVTX_PROFILING. RAY_CGRAPH_ENABLE_TORCH_PROFILING = ( os.environ.get("RAY_CGRAPH_ENABLE_TORCH_PROFILING", "0") == "1" )

底层实现:执行循环中挂载 torch.profiler

开启后,每个 Actor 的do_exec_tasks执行循环会在进入无限调度循环前启动torch.profiler.profile,并同时采集 CPU 与 CUDA 活动、记录调用栈,通过 TensorBoard trace handler 落盘,见 python/ray/dag/compiled_dag_node.py:

if RAY_CGRAPH_ENABLE_TORCH_PROFILING: assert ( not RAY_CGRAPH_ENABLE_NVTX_PROFILING ), "NVTX and torch profiling cannot be enabled at the same time." import torch torch_profile = torch.profiler.profile( activities=[ torch.profiler.ProfilerActivity.CPU, torch.profiler.ProfilerActivity.CUDA, ], with_stack=True, on_trace_ready=torch.profiler.tensorboard_trace_handler( "compiled_graph_torch_profiles" ), ) torch_profile.start()

要点:

  • 每个参与编译图的 Actor 都会各自启动一个 profile 实例,因此每个 Actor 生成一份独立的 trace 文件
  • 结果输出到当前工作目录下的compiled_graph_torch_profiles目录;
  • with_stack=True会记录 Python 调用栈,方便定位到用户方法;
  • 同时采集 CPU 与 CUDA 活动,可观察 GPU 内核执行与 CPU 侧调度的时间关系。

查看与可视化 trace

运行结束后,用浏览器打开 https://ui.perfetto.dev/(Perfetto UI),将compiled_graph_torch_profiles目录下的 trace 文件拖入即可查看时间线。通过对比各 Actor 的时间线,可以直观发现:

  • 某个 Actor 的执行循环是否长时间处于空闲(等待上游数据/通信通道);
  • 方法调用与 NCCL 传输在时间轴上的重叠程度;
  • 单个 task 在 CPU 与 GPU 上的耗时构成。

Nsight Systems:通过 runtime_env 启用系统级剖析

前置:为 Actor 配置 nsight runtime_env

Compiled Graph 建立在 Ray 既有 profiling 能力之上。要开启 Nsight 剖析,不需要改脚本执行方式,而是为涉及的 Actor 指定runtime_env={"nsight": ...},具体配置方式参考 Ray 的 Nsight 使用说明。nsight配置项可以是字符串"default"(使用默认配置),也可以是 Nsight Systems 选项的字典,参见 doc/source/ray-core/handling-dependencies.rst 对 runtime_envnsight键的说明。

完整示例:构建编译图并执行

以下代码来自仓库示例 doc/source/ray-core/doc_code/cgraph_profiling.py,先创建带 Nsight runtime_env 的 GPU Actor:

import ray import torch from ray.dag import InputNode @ray.remote(num_gpus=1, runtime_env={"nsight": "default"}) class RayActor: def send(self, shape, dtype, value: int): return torch.ones(shape, dtype=dtype, device="cuda") * value def recv(self, tensor): return (tensor[0].item(), tensor.shape, tensor.dtype) sender = RayActor.remote() receiver = RayActor.remote()

然后按常规方式构建并编译 DAG,注意这里通过with_tensor_transport(transport="nccl")指定张量走 NCCL 通道传输:

shape = (10,) dtype = torch.float16 # Test normal execution. with InputNode() as inp: dag = sender.send.bind(inp.shape, inp.dtype, inp[0]) dag = dag.with_tensor_transport(transport="nccl") dag = receiver.recv.bind(dag) compiled_dag = dag.experimental_compile() for i in range(3): shape = (10 * (i + 1),) ref = compiled_dag.execute(i, shape=shape, dtype=dtype) assert ray.get(ref) == (i, shape, dtype)

最后按常规方式运行脚本:

python3 example.py

执行结束后,Compiled Graph 会将剖析结果输出到/tmp/ray/session_*/logs/{profiler_name}目录下(session_*为本次 Ray 会话目录,{profiler_name}为 profiler 名称)。

NVTX:细粒度方法级标注

如果希望对方法调用与系统开销做更细粒度的分析,可额外设置环境变量:

RAY_CGRAPH_ENABLE_NVTX_PROFILING=1 python3 example.py

该开关在 python/ray/dag/constants.py 中定义。开启后,Compiled Graph 在底层利用 NVTX(NVIDIA Tools Extension Library)自动为编译图各 Actor 执行循环中调用的所有方法添加标注,使 Nsight Systems 时间线上能清晰地区分每个方法调用的起止,见 python/ray/dag/compiled_dag_node.py:

if RAY_CGRAPH_ENABLE_NVTX_PROFILING: assert ( not RAY_CGRAPH_ENABLE_TORCH_PROFILING ), "NVTX and torch profiling cannot be enabled at the same time." try: import nvtx except ImportError: raise ImportError( "Please install nvtx to enable nsight profiling. " "You can install it by running `pip install nvtx`." ) nvtx_profile = nvtx.Profile() nvtx_profile.enable()

需要注意的是:

  • 使用 NVTX 剖析前需要安装nvtx包:pip install nvtx
  • NVTX 与 Torch profiling 二者互斥,不能同时开启(源码中通过assert强制校验);
  • 剖析结果的查看方式与 Ray 常规的 Nsight 剖析结果相同,即打开 Nsight Systems 分析/tmp/ray/session_*/logs/{profiler_name}下的结果文件。

三种 profiling 开关小结

环境变量作用输出位置依赖备注
RAY_CGRAPH_ENABLE_TORCH_PROFILING=1启动 torch.profiler,采集 CPU/CUDA 活动当前目录compiled_graph_torch_profiles/,每个 Actor 一份 tracetorch与 NVTX 互斥
runtime_envnsight: "default"启动 Nsight Systems 系统级剖析/tmp/ray/session_*/logs/{profiler_name}Nsight Systems通过 runtime_env 配置
RAY_CGRAPH_ENABLE_NVTX_PROFILING=1NVTX 自动标注执行循环中的方法调用随 Nsight 结果一起pip install nvtx与 Torch profiling 互斥

可视化编译图结构

基本用法

剖析着眼于"时间",而理解"结构"则需要可视化。在调用experimental_compile()编译图之后,调用CompiledDAG.visualize()即可将图结构导出。来自 doc/source/ray-core/doc_code/cgraph_visualize.py 的完整示例:

import ray from ray.dag import InputNode, MultiOutputNode @ray.remote class Worker: def inc(self, x): return x + 1 def double(self, x): return x * 2 def echo(self, x): return x sender1 = Worker.remote() sender2 = Worker.remote() receiver = Worker.remote() with InputNode() as inp: w1 = sender1.inc.bind(inp) w1 = receiver.echo.bind(w1) w2 = sender2.double.bind(inp) w2 = receiver.echo.bind(w2) dag = MultiOutputNode([w1, w2]) compiled_dag = dag.experimental_compile() compiled_dag.visualize()

默认情况下,Ray 会在当前工作目录生成名为compiled_graph.png的 PNG 图片。注意这需要安装graphvizpip install graphviz),否则会抛出 ImportError,见 python/ray/dag/compiled_dag_node.py。

接口签名与参数

visualize()的完整签名(来自 python/ray/dag/compiled_dag_node.py):

def visualize( self, filename: str = "compiled_graph", format: str = "png", view: bool = False, channel_details: bool = False, ) -> str:
参数默认值说明
filename"compiled_graph"输出文件名(不含扩展名);ASCII 格式下该参数被忽略
format"png"输出格式,如pngpdfjpegascii则直接打印到控制台
viewFalse非 ASCII 格式下是否用默认查看器打开;ASCII 格式下是否打印并返回
channel_detailsFalseTrue时在边上附加通道类型与细节;与ascii格式不兼容

返回值:对 Graphviz 格式(png/pdf/jpeg 等)返回图的 DOT 字符串表示;对 ASCII 格式返回 ASCII 字符串。

读图:节点与边的含义

下面这张图展示了上述示例代码的可视化结果。同一 Actor 的任务使用相同颜色,可以据此快速识别任务所属的 Actor 以及任务间的依赖关系。

结合 python/ray/dag/compiled_dag_node.py 的绘制逻辑,节点标注规则如下:

  • InputNode(蓝色矩形)与InputAttributeNode(蓝色矩形):图的输入;
  • ClassMethodNode(椭圆,按 Actor 着色):标注为Actor: <类名>ID: <Actor ID 前 6 位>...Method: <方法名>,是图中最核心的节点;
  • MultiOutputNode(黄色矩形):图的汇合输出点;
  • 同色椭圆即属于同一 Actor 的任务,边表示数据流依赖方向;
  • 若设置channel_details=True,边上还会标注通道类型(如 NCCL)与传输细节。

这张图可以帮助你在剖析之前确认:数据流是否如预期地在各 Actor 之间传递、是否存在意外的串行依赖、多个输入分支是否真正并行。

实战建议:如何系统性定位编译图瓶颈

综合以上三套工具,推荐按以下步骤定位 Compiled Graph 的性能瓶颈:

  1. 先用visualize()检查结构:确认 DAG 编译结果符合预期(Actor 归属、任务依赖、并行分支),排除结构性问题;
  2. 开启 PyTorch profiling 观察任务级耗时RAY_CGRAPH_ENABLE_TORCH_PROFILING=1跑一次,在 Perfetto 中对比各 Actor trace,定位单个 task 的 CPU/GPU 耗时与空闲等待;
  3. 开启 Nsight + NVTX 深入系统开销:为 Actor 配置runtime_env={"nsight": "default"},配合RAY_CGRAPH_ENABLE_NVTX_PROFILING=1,在 Nsight Systems 中观察调度、通信(NCCL)与用户方法调用的时间线细节;
  4. 交叉验证:注意 NVTX 与 Torch profiling 互斥,两套剖析需要分开运行;剖析本身会引入一定开销,建议用多次运行的平均趋势而非单次结果做结论。

参考路径速查

  • 官方文档源文件:doc/source/ray-core/compiled-graph/profiling.rst
  • 剖析开关定义:python/ray/dag/constants.py
  • 剖析挂载与执行循环实现:python/ray/dag/compiled_dag_node.py
  • Nsight 剖析示例:doc/source/ray-core/doc_code/cgraph_profiling.py
  • 可视化示例:doc/source/ray-core/doc_code/cgraph_visualize.py
  • 可视化输出示例图:doc/source/images/compiled_graph_viz.png
  • runtime_envnsight配置说明:doc/source/ray-core/handling-dependencies.rst

【免费下载链接】rayRay is an AI compute engine. Ray consists of a core distributed runtime and a set of AI Libraries for accelerating ML workloads.项目地址: https://gitcode.com/gh_mirrors/ra/ray

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询