Ray Flow Insight:让分布式AI系统调试不再是“黑盒”难题

蚂蚁开源Ray Flow Insight,解决分布式AI系统调试难题。通过多维度可视化,让强化学习等复杂系统的内部运作更透明,助力开发者快速定位问题。

原文标题:AI开源框架:让分布式系统调试不再"黑盒"

原文作者:阿里云开发者

冷月清谈:

本文介绍了蚂蚁集团开源的AI计算框架AntRay中集成的Ray Flow Insight工具,旨在解决分布式AI系统,尤其是强化学习系统调试难的问题。随着AI计算范式的演进和上层AI框架的快速发展,强化学习系统的复杂性日益增加,开发者面临局部视图可视性不足、性能瓶颈识别困难、资源利用率监控复杂、调试信息分散等挑战。Ray Flow Insight通过可视化Ray的核心编程原语(Actor、Task、Object)及其交互关系,提供了逻辑视图、物理视图、分布式调用栈和分布式火焰图等多维度透视能力,使开发者能够直观理解系统行为,快速定位和解决问题。文章还通过AReaL、OpenRLHF和veRL三个强化学习框架的实战案例,展示了Ray Flow Insight在实际应用中的效果,并且对Ray Flow Insight的未来发展方向做出了展望,例如:完善容错机制,扩展语言支持,实现智能异常检测以及时序快照回溯等。

怜星夜思:

1、Ray Flow Insight 通过可视化 Actor, Task 和 Object 解决了分布式系统的黑盒问题,那么除了可视化,还有没有其他方式能解决这个问题?
2、文章中提到了Ray Flow Insight的规模限制,仅适用于Actors和Tasks实例数相对有限的应用场景,如果在actor数量非常多的情况下,有什么优化的思路吗?
3、Ray Flow Insight 目前主要针对Python应用,未来如果扩展到Java和C++,会面临哪些挑战?

原文内容

作为面向AI计算的开源框架,Ray 已在深度学习训练、大规模推理服务、强化学习以及AI数据处理等领域构建了丰富而成熟的技术生态。基于Ray构建的上层AI框架(如RayData、RayTrain、RayServe、AReaL、OpenRLHF、veRL等)正在成为AI研发的关键工具,尤其在后训练时代的强化学习场景中,这些框架为复杂的任务提供了高效、可扩展的分布式执行环境。

在蚂蚁内部,我们基于业务实践,不断深化对Ray的应用和优化,积累了丰富的分布式系统建设经验。这些实践中沉淀的技术能力会推动Ray生态在实际场景中的应用深度和广度。我们激活的AntRay开源社区,会始终保持与官方Ray版本强同步(即AntRay会紧随Ray官方社区版本而发布),后续也会以系列文章形式同步蚂蚁推向开源的新特性。本文将首先重点介绍:Ray Flow Insight —— 让分布式系统调试不再"黑盒"

ant-ray仓库地址:https://github.com/antgroup/ant-ray

一、后训练时代:复杂强化学习系统"黑盒"困境

随着AI计算范式的迅速迭代(从单机到多机、从单一模型到复合模型链、从同构到异构计算),以及基于Ray构建的上层AI框架的快速演进,计算节点数量激增、数据流量暴涨、模型参数规模扩大,强化学习系统的复杂性已远超传统机器学习范式,其内部运作机制变得难以追踪和理解。主要体现在以下几个方面:

图片

PPO算法两阶段流程: 图例来源参考资料[7]

局部视图下的可视性缺乏

传统的调试工具通常针对单机应用程序设计,无法有效展示分布式系统中组件之间的复杂交互。尤其是在规模较大的系统中,开发者很难全面了解系统的执行流程和数据流向。算法工程师和系统开发者只能看到各自负责部分的运行状态,却无法获得整体系统的全局视图。例如,在RLHF训练中,存在多种角色:Actor、Critic、Reward、Reference,角色彼此可能分散在不同节点,开发者通常只能观察到单个角色的行为,而难以理解它们之间复杂的互动关系。

性能瓶颈识别困难

在分布式强化学习环境中,性能问题可能来自多个源头:网络延迟、资源争夺、负载不均衡等。由于缺乏全局视图,开发者常常依赖于日志分析和猜测,这通常需要花费大量时间来定位性能瓶颈。对于强化学习系统而言,这一问题尤为突出,因为训练过程中的奖励计算、策略更新、环境交互等环节相互依赖,任何一个环节的延迟都可能导致整体性能下降。

资源利用率监控复杂

分布式系统中的资源(CPU、MEM、GPU)分布在多个节点上,难以获得统一的资源利用率视图。在强化学习训练中,不同阶段对计算资源的需求差异很大:以训推分离方案为例,Actor和Rollout分属不同阶段。如何高效分配和调度这些异构资源,在缺乏系统化监控工具的情况下变得异常困难。

调试信息分散

分布式系统的日志和调试信息通常分散在多个节点上,收集和关联这些信息是一项耗时的工作。在强化学习系统中,这一问题更为突出,因为需要同时关注模型训练、环境交互、数据收集等多个方面的调试信息。缺乏集中式的调试视图,使得问题排查变得异常困难。

后训练时代的特殊挑战

后训练时代的强化学习正面临着日益复杂的系统需求,这些需求虽然推动了Ray分布式框架的广泛应用,但在系统全方位洞察方面仍面临诸多挑战:

  • 多角色资源编排可视化:强化学习系统中通常存在多种具有不同功能的角色组件,如Actor、Critic、Reward、Reference、ReplayBuffer等。Ray虽提供了灵活的资源管理和调度策略(如PlacementGroup、NodeAffinity)来优化这些角色的分布部署,但缺乏直观工具来可视化这些复杂编排策略及其性能影响,开发者往往只能依靠经验而非数据驱动的方式来进行资源优化决策。

  • 混合并行策略的协同理解:为应对大模型训练,现代系统同时采用专家并行、数据并行、模型并行、流水线并行等多维并行策略。这些并行维度在Ray分布式环境中交织形成复杂的执行网络,开发者迫切需要工具来可视化和理解这些并行策略的协同效果与潜在冲突。

  • 分布式反馈循环的依赖追踪:RLHF系统的核心在于其复杂的反馈循环机制,从人类偏好到奖励建模,再到策略优化,形成了多层嵌套的依赖网络。这些依赖在Ray分布式环境中分散执行,理解它们的时序关系和数据流向对系统优化至关重要,但现有工具提供的追踪能力有限。

  • 分布式卡点分析:在复杂的强化学习系统中,执行卡点可能出现在任何节点,且常因组件间的跨节点依赖而难以追踪。不同于单机环境下可直接使用pstack等工具查看进程堆栈,分布式环境中的卡点诊断需要开发者手动连接各节点逐一检查,效率低下。

小结:虽然Ray Dashboard提供了基础集群监控功能,但在应对前述分布式强化学习系统的复杂挑战时仍显局限。Ray生态系统虽为强化学习算法提供了灵活易用的分布式执行环境,但缺乏能够深度透视系统内部结构、数据流向与资源分配的专业分析工具,导致开发者在优化过程中常依赖经验推断而非数据驱动决策。

二、Ray的分布式编程模型:Actor、Task与Object

在深入探讨Ray Flow Insight之前,我们需要先了解Ray框架的核心分布式编程模型。Ray通过三种基本原语(Actor、Task、Object)为开发者提供了构建复杂分布式系统的基础,这些概念是理解Ray Flow Insight设计理念的关键。

RAY的三大核心编程原语

Task:无状态分布式函数

Task是Ray中最基本的计算单元,本质上是一个无状态的分布式函数执行。通过@ray.remote装饰器,普通Python函数可以转变为可远程执行的Task:
@ray.remote
def process_data(data_ref):
    data = ray.get(data_ref)
    result = do_process(data)
    return result
# 创建一个Normal Task处理数据并
result_ref = process_data.remote(some_data)
# 获取执行结果
result = ray.get(result_ref)
Task具有以下特点:
  • 无状态性:每次调用都是独立的,不保留前一次执行的状态
  • 并行执行:多个Task可以在集群中并行运行
  • 自动调度:Ray调度器负责将Task分配到合适的节点执行

Actor:有状态分布式对象

Actor是Ray中的有状态计算实体,本质上是一个分布式对象,在集群中的某个节点上实例化并常驻内存:
@ray.remote
class DataProcessor:
    def __init__(self):
        self.state = {}  # 内部状态

    def process(self, data):
        # 处理数据并更新内部状态
        self.state[data.id] = data
        return self.state

创建Actor实例

processor = DataProcessor.remote()

调用Actor方法

future = processor.process.remote(data)

获取处理结果

state = ray.get(future)

Actor的关键特性:

  • 状态保持:Actor可以在方法调用之间维护内部状态

  • 串行执行:Actor的方法默认是串行执行的,确保状态一致性

  • 资源绑定:Actor实例绑定到特定节点,避免状态转移开销

Object:分布式共享数据

Ray Object是分布式内存中的不可变对象,作为Task和Actor之间传递数据的媒介:
@ray.remote
def create_data():
    return large_dataset  # 返回Ray Object引用

@ray.remote
def process_data(data_ref):
    # data_ref是对Ray Object的引用,获取实际数据
    data = ray.get(data_ref)
    return processed_result
#生成一个大的数据对象引用,对象实例存放在Object Store中
data_ref = create_data.remote()

获取处理结果

result_ref = process_data.remote(data_ref)

Ray Object的特点:

  • 透明序列化:自动处理Python对象的序列化和反序列化

  • 分布式对象存储:数据存储在Ray的分布式内存中,可跨节点共享

  • 引用传递:通过引用而非数据副本传递,减少数据移动开销

  • 惰性求值:只有在需要时才会实际获取数据

分布式系统的交互复杂性

当使用Ray构建大规模分布式系统(如强化学习框架)时,系统的复杂性会随着规模的增长而呈指数级增加:
  • 组件交互网络数百甚至数千个Actor和Task之间形成复杂的调用关系网络
  • 多层依赖:Actor可能依赖其他Actor的输出,形成多层嵌套的依赖链
  • 资源分配:不同的Actor和Task可能分布在不同节点上,资源分配变得复杂
  • 数据流向:大量Ray Object在节点间流动,形成复杂的数据流网络
例如,在RLHF(基于人类反馈的强化学习)系统中,通常包括:1)多个Actor实例负责不同的角色(策略网络、价值网络、奖励模型等);2)复杂的Task调用关系处理数据预处理、模型更新等操作;3)大量的Ray Object在组件间传递(训练数据、模型参数、中间结果等)。这种复杂性使得系统行为难以理解和调试,在分布式系统中,问题可能出现在任何组件或组件间交互,而没有直观的方式去观察整个系统的运行情况。

分布式编程原语可视化

Ray Flow Insight的核心设计理念是将Ray的分布式编程原语(Actor、Task、Object)及其交互关系可视化,从而解决分布式系统的"黑盒"问题:
  • 原语可视化:
    • 将Actor实例转化为可视化节点,展示其内部状态和方法
    • 将Task调用转化为可视化节点,展示其执行状态和依赖关系
    • 将Object引用转化为数据流连接,展示数据在组件间的流动
  • 多维度透视:
    • 逻辑视图:抽象化Actor和Task的调用关系,展示系统拓扑结构
    • 物理视图:展示Actor和Task在物理节点上的分布,反映资源使用情况
    • 调用栈视图:提供类似传统调试器的调用堆栈,但跨越分布式边界
    • 火焰图视图:展示系统性能热点,帮助识别瓶颈
  • 零侵入设计:
    • 不修改用户代码即可自动收集系统运行信息
    • 基于Ray内部机制捕获Actor、Task和Object的交互数据
    • 提供简单API接口支持高级定制需求(如上下文标记)
通过这种基于Ray原语的可视化方法,Ray Flow Insight能够将复杂的分布式系统变得透明化,让开发者能够直观地理解系统行为,快速定位和解决问题,接下来我们将详细介绍Ray Flow Insight工具的具体功能和使用方法,展示它如何通过多维度可视化来解决分布式系统的调试和优化挑战。

三、Ray Flow Insight:分布式应用可视化分析工具

Ray Flow Insight 是蚂蚁集团专为解决Ray分布式应用"黑盒"问题设计的可视化分析工具,为复杂分布式系统提供多维度透视能力,它采用"零侵入式"设计理念,大部分功能无需修改用户代码即可自动收集并可视化系统运行状态,同时提供灵活API接口支持高级定制需求。

Ray Flow Insight 通过四个互补的可视化视图,从不同角度解析分布式系统特性:

  • 逻辑视图(Logical View):展示组件间的调用关系和数据依赖,帮助理解系统拓扑结构
  • 物理视图(Physical View):展示组件在节点间的分布和资源使用情况,帮助优化部署策略
  • 分布式调用栈(Distributed Stack):提供跨节点的调用链路追踪,快速定位执行卡点
  • 分布式火焰图(Distributed Flame Graph):可视化系统性能热点分布,指导精准优化

这些功能相互配合,为开发者提供了从宏观到微观、从静态到动态的全方位系统洞察能力,使分布式强化学习系统的开发和调优从"盲目摸索"转变为"数据驱动决策"。


接下来我们以一个基于Ray构建的分布式应用为例,详细介绍Ray Flow Insight的核心功能模块:

import ray
import random
import time

ray.init(address=“auto”)

@ray.remote
class Worker:
    “”"
    Create a tree of workers in which each worker spawns multiple children.
    “”"
    def init(self, depth, is_bottleneck=False):
        # Whether this worker should mock delay
        self.is_bottleneck = is_bottleneck
        # Current depth in the worker tree (root = highest number)
        self.depth = depth
        # List to store child worker actor references
        self.children =

        # Create child workers if we’re not at a leaf node (depth > 0)
        if self.depth > 0:
            # Create 1-2 children randomly for each worker
            for _ in range(random.randint(1, 2)):
                # Recursively create child workers with decreased depth
                # Randomly decide if the child will be a bottleneck
                self.children.append(
                    Worker.remote(
                        depth=self.depth - 1,
                        is_bottleneck=random.randint(0, 1) == 1
                    )
                )

    def process(self):
        “”"
        Process work and delegate to child workers.
        Bottleneck workers at leaf nodes introduce significant delays.
        “”"
        # List to collect all async task references from children
        futures =

        # For each child worker
        for child in self.children:
            # Submit 10 process tasks to each child
            for _ in range(10):
                # If this is a bottleneck worker at a leaf node (or just above),
                # introduce a significant delay (20 seconds)
                if self.is_bottleneck and self.depth - 1 <= 0:
                    time.sleep(20.0)

                # Standard processing time for all workers (2 seconds)
                time.sleep(2)

                # Submit the process task to the child worker
                # This creates a nested tree of task calls
                futures.append(child.process.remote())

        # Wait for all child tasks to complete before returning
        # This ensures the full tree of tasks must complete
        ray.get(futures)

Create the root worker with depth 5

This will create a tree of workers with maximum depth of 5

worker = Worker.remote(depth=5, is_bottleneck=False)

Start processing and wait for the entire tree to complete

ray.get(worker.process.remote())

这是一个基于Ray构建的典型多层实例的分布式应用,Driver会创建一组5层拓扑结构的Worker实例,每一层Worker实例在构造时会随机创建1~2个下游异构实例,对于最后一层bottleneck的实例,在执行任务时耗时会长一些,用于模拟长尾任务。

逻辑视图

逻辑视图是用于展示基于Ray构建的分布式应用中Actors以及Normal Tasks之间的逻辑调用和任务间数据依赖与流转拓扑关系。无需用户额外代码注入,Ray Flow Insight 便可自动解构并渲染框架拓扑,对算法以及工程同学学习了解一些依赖Ray构建的分布式应用(如OpenRLHF、veRL等)组件及其之间交互流程非常有帮助。
下图是通过上述代码示例渲染出的逻辑视图:
p_logic.gif

逻辑视图说明:

    • 黄色圆形框:代表Driver入口方法

    • 黄色矩形框:代表Ray Normal Task

    • 蓝色矩形框:代表Ray Actor实例

    • 绿色矩形框:代表Ray Actor Method方法

    • 黑色实线边:代表任务控制流,两端分别连着 Caller 和 Callee,箭头代表调用关系,线上数字代表调用次数

    • 红色虚线边:代表数据流,可以是方法的入参,也可以是任务的返回值(目前仅记录含Ray Object的数据),粗细代表最后一次数据传输速率(选中后右侧可观测详细信息),箭头代表流向

    通过Ray Flow Insight的逻辑视图,研发人员能够直观把握整个分布式系统的组件拓扑结构与交互模式,实现对复杂分布式系统的全局理解。这种可视化不仅展现了静态的组件间关系,更揭示了动态的控制流和数据流的流转路径,使开发者能够精确定位通信瓶颈、识别数据依赖热点、发现冗余调用模式,并洞察组件间的负载分布不均衡现象。

    物理视图

    与逻辑视图展示Actors及Normal Tasks之间调用关系不同的是,物理视图主要用于展示Ray作业内Actors及NormalTasks在不同节点上的分布及资源使用情况,帮助研发人员快速定位热点实例及节点。

    下图是通过上述代码实力渲染出的物理视图:

    p_phy.gif

    物理视图所有元素均采用矩形框表示,每一个矩形框都采用「血槽」填充的方式表示其资源用量:

    • Ray Node:单个Ray节点,采用浅绿色血槽表示资源用量

    • Placement Group:通过Ray接口预留的资源组,采用淡蓝色血槽表示资源用量,可以装载Actors或者Tasks

    • Actor:Ray的Actor实例,内层矩形框,采用Actor Name随机颜色血槽表示其真实资源用量

    • Normal Task:物理视图暂未支持Normal Task(开发中)

    • Resource Usage:当前默认提供CPU、MEM、GPU资源使用情况透出,选择不同资源,对应血槽也会改变

    • Actor Context:需要用户显示地使用insight接口给实例注册label,物理视图可以根据label进行过滤筛选(如强化场景显示地给Actor注册EP、PP、DP并行策略对应的RANK ID)

      分布式火焰图

      火焰图(Flame Graph)是单机性能剖析的重要工具,通过可视化调用栈的执行时间分布,帮助开发者直观识别程序中的性能热点。然而,在Ray分布式环境中,性能问题往往分散在多个节点和组件之间,传统火焰图无法展现这种跨节点的性能特征。

      Ray Flow Insight提供的分布式火焰图(Distributed Flame Graph)能够自动收集和汇总单个Ray作业的全生命周期所有组件的执行时间数据,构建一个覆盖全系统的统一火焰图,使开发者能够一目了然地看到分布式组件调用关系以及各环节耗时情况,进而分析整个分布式系统中的性能瓶颈。

      同样,针对上述代码示例,从FlameGraph视图我们可以观察到其中某个process执行时间timeline为26.24s,占了绝大多数执行时间。

      图片

      分布式调用栈

      在单机环境中,当应用程序出现卡顿或死锁时,开发者通常会使用pstack等工具打印进程的调用栈信息,快速定位问题所在。然而,在Ray分布式系统中,特别是复杂的强化学习应用场景,问题排查变得异常困难。当系统中某个组件卡住时,传统方法需要开发者逐一登录每个节点,挨个检查进程状态,不仅效率低下,更难以发现跨节点交互导致的复杂问题。

      Ray Flow Insight提供的DStack(Distributed Stack),能够自动收集并可视化整个Ray集群中所有Actor和Task的调用关系,呈现一个统一的、跨节点的"调用栈视图",让开发者能够:

      • 无感接入:无需用户主动注入,只需使用ray api native方式编写分布式程序
      • 一览全局:在单一界面中查看整个分布式系统的调用栈状态
      • 追踪依:识别组件间的调用依赖关系,发现潜在的死锁或性能瓶颈
      • 定位阻塞:快速定位哪些组件被阻塞,以及它们被阻塞的原因

      针对上述示例代码的运行过程中的DStack视图如下:

      图片

      在DStack视图中,可以认定那些调用次数长期不变的节点为卡钝节点,以此可以定位系统瓶颈,识别潜在的问题。

      实例列表

      整个面板的左侧是instances列表,它包含了所有的Actor和Normal Task,提供了搜索和定位功能。

      • 搜索:在四种视图下,当我们搜索某个关键字,对应的元素会在视图中高亮显示出来 ,其他不匹配的元素则会隐藏/透明显示。

      • 定位:在逻辑视图和DStack视图下,当我们点击某一个元素(Actor,Normal Task或者Method)时,会自动定位并放大图中的特定元素。

      组件详情

      整个面板的右侧是Component Details,它包含了具体元素的具体信息,在每个视图中,当我们点击不同元素,右侧视图会显示不同信息:

      • Actor:显示Actor ID、PID、Devices、Methods、Caller、Callee及数据依赖等信息
      • Method:显示对应的Actor、Caller、Callee以及数据依赖等信息
      • Normal Task:显示Caller、Callee以及数据依赖等信息

      适用场景及局限性

              规模限制前Ray Flow Insight会收集所有Actors和Tasks实例的调用及数据流转关系,所以目前仅适用于Actors和Tasks实例数相对有限的应用场景,如果基于Ray构建的应用,存在不断创建和销毁Actor的情况,随着时间的推移,会导致Flow Insight的渲染压力较大,影响Dashboard的稳定性。

              语言限制当前Release的Flow Insight版本仅支持Python应用的渲染,Java和C++待支持

              四、实战案例:AReaL、OpenRLHF与veRL强化学习框架Profiling

              为了展示Ray Flow Insight在实际应用中的能力,我们以蚂蚁和清华大学联合开源的强化学习框架AReaL以及另外两个业界熟知的强化学习框架OpenRLHF和veRL为例,详细介绍工具的使用方法和实际效果。

              安装与配置

              我们在ant-ray的2.44.1.1版本中正式Release了Ray Flow Insight功能,只需在启动Ray集群前设置相应的环境变量即可启用Ray Flow Insight功能。

              # Using --target and setting PYTHONPATH is to solve the package conflict problem
              # caused by relying on both ant-ray and ray. For example, if the user relies on
              # ant-ray and vllm (which relies on ray) at the same time
              pip install ant-ray==2.44.1.1 --target /home/admin/ant-ray
              export PYTHONPATH=/home/admin/ant-ray:$PYTHONPATH
              # Enable Ray Flow Insight
              export RAY_FLOW_INSIGHT=1
              # For head node
              ray start --head xxx
              # For work node
              # ray start --address=xxx
              

              AReaL框架案例分析

              AReaL是蚂蚁技术研究院和清华大学联合发布的开源强化学习系统,基于SGLang推理引擎,以高效率高稳定性为特点。在最新的 AReaL v0.2 版本 AReaL-boba 中,其 7B 模型数学推理分数刷新同尺寸模型 AIME 分数纪录,并且仅仅使用 200 条数据复刻 QwQ-32B,以不到 200 美金成本实现最强推理训练效果


              详见: 200美金,人人可手搓QwQ,清华、蚂蚁开源极速RL框架AReaL-boba

              https://zhuanlan.zhihu.com/p/1889988181006467307

              在蚂蚁集团的AI基础设施生态中,AReaL强化学习框架聚焦于大模型强化学习训练的高效实现和成本降低,Ray聚焦于分布式及AI计算的异构资源管理及任务调度协调,高效的强化学习系统与灵活的AI计算框架,相互协同共同支撑强化学习相关业务,旨在降低后训练时代技术门槛。

              下面简单介绍我们基于AReaL开源的数据集和7B模型训练脚本,采用双节点16H800计算卡进行测试案例分析。

              测试环境
              • 算法:使用veRL框架执行GRPO算法
              • 节点数:2 个节点,共16张H800计算卡
              • BaseModelqwen2.5 7B
              • RolloutSGLang
              • 精度:FF16
              逻辑视图: AReaL系统透视

              通过逻辑视图分析发现,AReaL系统主要由多个_QueueActormodel_worker以及master_worker组成。整体呈现出典型的生产者-消费者架构模式,通过队列进行通信和任务分发。

              图片


              架构透视

              • 分布式Actor模型架构
                • Actor组件设计:基于Ray Actor模型构建,由多个QueueActor和ModelWorker组成
                • 主从协调模式:主控工作器(MasterWorker)负责协调和调度其他ModelWorker
              • 生产者-消费者工作模式
                • 队列通信机制:通过队列实现组件间任务分发和结果返回
                • 非阻塞设计:大量使用get_nowait非阻塞调用进行轮询检查
                • 轮询操作模式:初始化后以短轮询操作为主要工作模式
              • 异步通信架构
                • 批处理特性:数据以批处理方式在组件间传递
                • 短消息交互:组件间传递小型数据包,所有数据流的大小完全相同(0.00005436 MB),平均传输时间约0.0038秒
                • 异步结果返回:任务完成后结果通过队列异步返回

              主要组件分析

              图片
              物理视图: 资源分配与使用观测

              通过物理视图,很容易观测到系统部署在两个物理节点上,每个节点配备8张NVIDIA L20Y GPU(每张约80GB显存),64核CPU以及约750GB的内存。

              图片

              资源分配状态

              1. CPU利用率:
              • 节点1:CPU使用率约1.5%,负载较轻
              • 节点2:CPU使用率约9.9%,负载适中
              2. 内存使用
              • 节点1:19.7%(使用约159GB,剩余约646GB)
              • 节点2:5.6%(使用约45GB,剩余约760GB)
              3. GPU分配
              • 节点1:8张GPU分配给了model_worker(8~15)
              • 节点2:6张GPU分配给了model_worker(1,3-7),总体比较活跃,有2张GPU(0,2)处于空闲状态
              分布式火焰图: 瓶颈分析
              图片

              火焰图数据显示系统以初始化阶段开始,随后进入大量轮询操作模式。主要调用模式如下:

              • get_nowait方法调用为主导(占总调用次数的95%以上)
              • 每个model_worker执行大量轮询操作,每秒数百次get_nowait调用
              • putget方法调用相对较少,通常每个组件仅2-3次
              分布式调用栈

              从当前调用栈可以看出正在处于get_nowait轮询阶段,调用总次数在4k多,由此可以看出是高频短轮询。

              图片

              veRL框架案例分析

              veRL是字节开源的强化学习框架,在我们的实验中,我们启动了一个单机8卡的veRL作业,并使用Ray Flow Insight进行可视化分析。

              测试环境
              • 算法:使用veRL框架执行GRPO算法
              • 节点数:1 个节点,8张A100计算卡
              • BaseModel:DeepSeek-Coder-V2-Lite-Instruct
              • Rollout:采用VLLM(实例数:2,TP为4)
              • 精度:BF16

              为了区分不同的Actor角色,我们修改了部分veRL的代码(single_controller/ray/base.py):

              for key, user_defined_cls in cls_dict.items():
                  user_defined_cls = _unwrap_ray_remote(user_defined_cls)
                  _bind_workers_method_to_parent(WorkerDict, key, user_defined_cls)
                  # NOTE:Modify the cls name to make the Ray Actor more clear.
                  WorkerDict.__name__= user_defined_cls.__name__
              


              逻辑视图: veRL系统透视

              在逻辑视图中,我们可以看到2类Ray Actor: register_center、ActorRolloutRefWorker,2类Normal Task:main_task、bundle_reservation_check_fun,这些都是veRL框架基于Ray的API进行控制面的一些操作。

              verl_log.gif

              我们可以看到,veRL框架遵循带有分布式执行的中央协调模式:

              • 系统由一个注册中心actor(register_center)和八个rollout actor(ActorRolloutRefWorker_0:0到ActorRolloutRefWorker_0:7)组成

              • 调用流程显示一个星形模式,其中主函数(main_task)直接调用所有worker actor上的方法。worker actor之间没有直接通信,这表明采用了中央控制模型。

              关于veRL更详细的解读可以参考:从零开始的verl框架解析
              https://zhuanlan.zhihu.com/p/30876678559?utm_psn=1888157484339934133
              物理视图: 资源分配与使用观测
              物理视图中,我们能看到程序运行在一个配备有8个NVIDIA A100-SXM4-80GB GPU的单节点上,所有的ActorRolloutRefWorker都被放置到了一个节点的矩形框中(即:这些ActorRolloutRefWorker都放置在一个PlacementGroup中),通过对资源进行筛选,我们可以看到每个WorkerRolloutRefWorker在对应资源上的消耗情况。
              图片
              系统中的Ray Actor分为两类:

              • 注册中心 (register_center):

                • 不占用任何专用GPU资源

                • 内存占用较小(约159MB RSS)

                • CPU使用率低(0.3%)

                • 作为协调者而非计算节点运行

              • Worker节点 (ActorRolloutRefWorker_0:0 到 ActorRolloutRefWorker_0:7):

                • 每个worker被分配一个专用GPU

                • CPU使用率非常高(~100.7-100.8%),表明是计算密集型工作

                • 内存占用大且均衡(约68GB RSS)

                • 每个worker被分配到特定编号的GPU上

              除此之外,我们还在veRL框架中注册了pp、dp、tp等上下文,便于在物理视图上快速定位Actor or GPU卡对应的rank id信息:
              图片
              veRL代码上下文注册代码如下(代码路径: single_controller/base/megatron/worker.py):
              def get_megatron_rank_info(self):
                  from megatron.core import parallel_state as mpu
                  tp_rank = mpu.get_tensor_model_parallel_rank()
                  dp_rank = mpu.get_data_parallel_rank()
                  pp_rank = mpu.get_pipeline_model_parallel_rank()
                  cp_rank = mpu.get_context_parallel_rank()
                  info = DistRankInfo(tp_rank=tp_rank, dp_rank=dp_rank, pp_rank=pp_rank, cp_rank=cp_rank)
                  # NOTE: Register tp/dp/pp context.
                  from ray.util.insight import register_current_context
                  register_current_context({"tp_rank": tp_rank, "dp_rank": dp_rank, "pp_rank": pp_rank, "cp_rank": cp_rank})
                  return info
              

              通过这些上下文信息,我们可以在 Flow Insight 中:

              • 按 "pp_rank" 过滤,查看流水线并行的rank
              • 按 "dp_rank" 过滤,查看数据并行的rank
              • 按 "tp_rank" 过滤,查看tens or并行的rank

              同时我们可以进行上下文搜索,筛选出我们需要的上下文对应的Actor。

              分布式火焰图: 瓶颈分析

              下图展示了verl的分布式火焰图,我们可以看到执行各个阶段不同调用的执行时间和占比

              图片

              我们可以看到如下性能瓶颈:

              • 样本生成阶段是明显的性能瓶颈,占总执行时间约70%,优化此阶段将带来最大的整体性能提升
              分布式调用栈: 

              下图展示了verl的分布式调用栈,可以看到目前在get_megatron_rank_info阶段。

              图片

              OpenRLHF框架案例分析

              测试环境
                      • 算法:使用OpenRLHF框架执行PPO算法

                      • 节点数:2 个节点,每个节点4张A100计算卡

                      • BaseModel:Qwen2.5-7B-Instruct

                      • Rollout:采用VLLM(实例数:4,TP为1)

                      • 精度:BF16


                      逻辑视图: OpenRLHF系统透视

                      全局视图如下

                      • 我们可以看到中间的圆形main,它代表着driver
                      • 从driver有很多条控制边,指向不同的Actor的方法和不同的Normal Task
                      • 不同的Actor Instances对应不同蓝色的框,我们可以看到三种Ray Actor:LLMRayActor、ActorModelRayActor、 ReferenceModelRayActor
                      • 黄色的方框代表Normal Task,我们可以看到两个Normal Task:bundle_reservation_check_func、reward_func
                      图片

                      通过逻辑视图,我们梳理出如下调用模式:

                      • _main函数初始化所有Ray Actor及其方法:
                        • 初始化每个actor
                        • 通过get_master_addr_port获取网络配置
                        • 使用init_model_from_pretrained加载模型
                        • 通过ActorModelRayActors的fit方法开始训练
                      • 训练过程展示了明确的RLHF模式:
                        • ActorModelRayActors调用fit,调用LLMRayActors的init_process_group初始化分布式进程
                        • ActorModelRayActors通过add_requests向LLMRayActors发送请求(数据大小约0.17-0.20MB)
                        • LLMRayActors通过get_responses响应(数据大小约2.2-2.8MB)
                        • 通过forward调用ReferenceModelRayActors(数据大小约0.007-0.017MB)
                        • 推理后,通过empty_cache调用管理GPU内存
                      • reward计算
                        • 所有四个ActorModelRayActors以相同频率(每个6次)调用reward_func函数
                        • reward计算返回非常小的数据(约0.0004MB)


                      我们可以分析调用频率和模式:

                      • 高频操作:
                      1. a.对Reference Model的forward操作(每个actor 6次调用)
                      2. b.empty_cache操作(每个actor 6次调用)
                      3. c.reward_func调用(每个actor 6次调用)
                      • 数据流大小:
                      1. a.最大的数据传输是LLMRayActors通过get_responses向ActorModelRayActors的传输(约2.2-2.8MB)
                      2. b.add_requests请求大小中等(约0.17-0.20MB)
                      3. c.推理结果和reward数据非常小(<0.02MB)
                      • 关键路径:
                        a.reward计算似乎是潜在瓶颈,每次调用需要1.2-1.5秒

                      关于OpenRLHF更详细的内容,可以参考:图解OpenRLHF中基于Ray的分布式训练流程https://zhuanlan.zhihu.com/p/12871616401

                      物理视图: 资源分配与使用观测

                      利用物理视图,我们可以观察actor的物理布局信息

                      图片

                      物理节点布局

                      系统在两个物理节点上运行:

                      • 节点ID:
                        a6967f22f166b7a65f229e70ddef8f8a60c4fe716d57a8149c969638
                        • 主要托管所有LLMRayActor
                      • 节点ID: 5165655b497cf5020b7298d95b98b6e15353b0a06435dba781ee54ab
                        • 托管所有ActorModelRayActor和ReferenceModelRayActor

                      资源配置与分配策略

                      LLM节点 (第一个节点)

                      • 每个LLMRayActor独占一个完整GPU
                      • 资源分配模式:严格1:1分配,每个Actor获得一个GPU和相应的CPU
                      • 所有GPU内存使用相似(约51GB,总容量81GB)

                      Actor和Reference节点 (第二个节点)

                      • 采用共享资源模式:
                        • 每个GPU由一对ActorModel和ReferenceModel共享
                        • ActorModel占用更多GPU内存(21-25GB)
                        • ReferenceModel占用较少GPU内存(约2.2-2.3GB)

                      内存和CPU使用模式

                      • MEM使用:
                        • LLMRayActor: 大约14.6GB RAM
                        • ActorModelRayActor: 约6.4GB RAM
                        • ReferenceModelRayActor: 约13.2GB RAM (尽管GPU内存使用小,但系统内存使用大)
                      • CPU使用:
                        • LLMRayActor: CPU使用率低(0.3-0.5%)
                        • ActorModelRayActor: CPU使用率中等(19.8-22.3%)
                        • ReferenceModelRayActor: CPU使用率高(32.1-51.2%)


                      总的来看,我们可以观察到如下几点:

                      1.系统采用了服务分离部署策略:
                        • 将大型LLM模型与Actor模型和reference模型分离到不同物理节点
                        • 减少资源竞争,提高系统稳定性
                      2.资源共享与优化:
                        • ActorModel和ReferenceModel共享GPU,但有不同的内存分配
                        • 每个GPU上分配的总内存使用不超过30GB(总容量81GB),保留足够缓冲空间
                      3.平衡负载分布:
                        • 每个物理节点上的负载均匀分布在4个GPU上
                        • 同类模型分配相似资源,确保性能一致性
                      4.CPU与GPU协同:
                        • reference model CPU使用率高,但GPU内存占用少,表明模型结构设计上的差异
                        • Actor model CPU和GPU使用更加平衡
                      分布式火焰图:瓶颈分析

                      通过分析Ray的火焰图数据,我可以深入了解OpenRLHF框架的执行流程、性能特征和潜在瓶颈。

                      图片

                      初始化与加载阶段

                      • 模型初始化耗时
                        • LLM model: 初始化时间约193-195秒,四个实例耗时相近
                        • Actor model: 初始化时间约5.3-5.6秒
                        • Reference model: 初始化时间约5.2-5.7秒
                      • 模型加载耗时
                        • Actor model加载: 所有四个实例的init_model_from_pretrained调用耗时约334-335秒
                        • Reference model加载: init_model_from_pretrained调用耗时约152-160秒
                        • 这表明Actor model比Reference model大约大2倍,且LLM model的初始化过程复杂。模型加载是整个工作流中最耗时的阶段。

                      训练阶段关键操作

                      • 分布式初始化
                        • init_process_group调用显示不同LLM实例初始化时间差异大, 最快的实例仅需0.006秒, 最慢的实例需要0.56秒, 这表明分布式同步存在不均衡性
                      • 请求处理
                        • add_requests调用耗时显著:前两个实例约75-76秒, 后两个实例约131秒, 这种差异表明请求批处理可能存在不平衡
                      • generation获取
                        • get_responses调用相对快速(0.025-0.033秒)
                        • 响应获取比请求添加快得多,说明大部分时间消耗在请求处理而非结果传输
                      • 模型前向传播
                        • 参考模型的forward调用(每个模型6次):总耗时约6.8-7.9秒, 平均每次调用耗时约1.1-1.3秒, 各模型间性能差异小于15%
                      • 内存管理
                        • empty_cache操作(每个模型6次):总耗时约1.6-1.9秒, 平均每次耗时约0.27-0.31秒, 表明GPU内存管理开销适中
                      • reward计算
                        • reward_func被调用24次(每个Actor模型6次):总耗时约4.17秒, 每次调用平均约0.17秒, 但不同Actor模型间差异显著:
                          • ActorModel 23c9 和 6ccc:总计约1.6-1.8秒
                          • ActorModel 90eb 和 920a:总计仅0.33-0.38秒
                          • 这种5倍差异表明奖励计算可能依赖于输入内容


                      分布式调用栈

                      截取某一时刻的DStack,我们可以看到目前正在进行ActorModel的fit操作。

                      图片


                      五、总结与展望

                      Ray Flow Insight 为分布式系统开发者提供了一个多维度灵活的可视化工具,弥补了传统调试工具在分布式环境中的不足。通过提供逻辑视图、物理视图、分布式火焰图和分布式调用栈四大核心功能,实现了对分布式系统内部运作机制的透明化展示,使开发者能够直观理解复杂系统的拓扑结构、资源分配、执行流程和性能瓶颈,专注于业务逻辑的优化,而不必被系统调试的复杂性所困扰。
                      未来Ray Flow Insight 有望在以下方面持续迭代:
                      • 完善的容错机制:提供数据模型持久化能力,使得RayInsightMonitor故障后能恢复
                      • 更广泛的语言支持:除了当前的Python支持,扩展到Java和C++等多语言环境
                      • 智能异常检测:识别资源使用异常、任务执行时间异常,分布式组件间的异常传播路径,帮助理解问题如何在系统中扩散
                      • 时序快照回溯:支持历史快照回溯功能

                      参考资料
                      [1] AReaL: Ant Reasoning Reinforcement Learning for LLMs(https://github.com/inclusionAI/AReaL)
                      [2] OpenRLHF: An Easy-to-use, Scalable and High-performance RLHF Framework
                      https://github.com/OpenRLHF/OpenRLHF)
                      [3] HybridFlow- A Flexible and Efficient RLHF Framework
                      https://arxiv.org/pdf/2409.19256v2)
                      [4] verl: Volcano Engine Reinforcement Learning for LLM
                      https://github.com/volcengine/verl
                      [5] 图解大模型RLHF系列之:人人都能看懂的PPO原理与源码解读
                      https://zhuanlan.zhihu.com/p/677607581)
                      [6] LLM强化学习算法演进之路:MC->TD->Q-Learning->DQN->PG->AC->TRPO->PPO->DPO->GRPO
                      https://zhuanlan.zhihu.com/p/20949520788)
                      [7] 图解OpenRLHF中基于Ray的分布式训练流程
                      https://zhuanlan.zhihu.com/p/12871616401)
                      [8] 从零开始的verl框架解析
                      https://zhuanlan.zhihu.com/p/30876678559)

                      [9] 200美金,人人可手搓QwQ,清华、蚂蚁开源极速RL框架AReaL-boba(https://zhuanlan.zhihu.com/p/1889988181006467307)

                      可以考虑使用更高效的数据结构和算法来存储和处理Actor的信息。例如,使用Bloom Filter来快速判断一个Actor是否存在,使用Skip List来加速Actor的查找。此外,还可以采用分布式存储方案,将Actor的信息分散存储在多个节点上。

                      可视化确实是直观的方式,但我觉得还可以结合一些监控指标的自动化分析。比如,可以设置一些阈值,当某些指标(如Actor的CPU使用率、Task的执行时间)超过阈值时,自动触发告警,并提供相应的诊断建议。

                      我觉得链路追踪技术也很重要,可以清晰地展示请求在各个服务之间的调用关系和耗时。结合服务依赖关系图,可以快速定位瓶颈。另外,还可以通过代码注入的方式,在关键路径上增加埋点,收集更详细的性能数据。

                      跨语言支持最大的挑战在于如何统一不同语言的抽象和概念。比如Actor,Task这些概念在不同语言里的实现方式可能不一样,需要找到一个通用的模型来描述它们,才能让Ray Flow Insight能够理解和可视化。还有,性能也是个大问题,需要在数据收集和分析的时候尽量减少对应用本身性能的影响。

                      针对Actor数量过多的情况,可以考虑采用抽样可视化的方法。例如,只可视化一部分具有代表性的Actor,或者根据某些指标(如CPU使用率、内存占用)筛选出关键的Actor进行可视化。此外,还可以对Actor进行分组,只展示分组级别的统计信息。

                      Java和C++的并发模型与Python不同,需要考虑如何准确地追踪多线程和多进程之间的调用关系。此外,Java和C++的异常处理机制也与Python不同,需要考虑如何处理跨语言的异常传播。

                      我觉得可以借鉴一下数据库分库分表的思路,把actors按照某种规则分散到不同的“视图”里,每次只加载部分“视图”的数据,这样可以降低单次加载的数据量。另外,是不是可以把历史数据归档,只保留最近一段时间的数据,减轻系统的压力。

                      除了可视化和监控告警,还可以考虑引入AI辅助诊断。通过机器学习算法分析系统的运行日志、调用链等数据,自动检测潜在的性能瓶颈和错误模式。这就像给系统装上一个“AI医生”,能够自动巡检并提出诊断报告。

                      Java和C++的内存管理机制与Python不同,需要考虑如何高效地收集和分析内存使用情况。此外,Java和C++的调试工具链也与Python不同,需要开发相应的插件或适配器,以便与Ray Flow Insight集成。