从零开始的 Ray 框架之旅(一)

1. 什么是 Ray 框架

Ray 框架是由 UC Berkeley RISELab 开发的开源分布式计算框架,不同于 Spark 这种围绕数据集(RDD) 进行抽象,也不同于 Pytorch 这种围绕模型(Tensor) 进行抽象,它从最基本的面向对象编程(OOP) 进行抽象。
Ray 的核心目标是构建「通用分布式」的能力,这种能力来源于其独特的计算引擎和 API 抽象设计,Ray Core的两个核心概念是 TaskActor:

  • Task 可以看做远程执行的、无状态的函数调用,这对应了 OOP 中的方法或函数。
  • Actor 可以看做是远程的、有状态的对象实例,这直接对应的 OOP 中的对象,它封装了状态和操作该状态的方法。

Ray 它不把自己限定在某个特定领域,而是提供了将通用 OOP 构件(函数和对象)进行分布式化和并行化的能力,这意味着它是一种更加普适的分布式计算「积木」式框架,你可以用它提供的「积木」来构建各种各样的分布式应用,包括上述提到的 SparkPytorch 可能不擅长的一些场景。
image.png

2. Ray 的核心特性和应用场景

image.png
Ray 通过直观的 Python API 简化分布式应用开发,实现对计算资源的透明访问。其核心优势包括:

  • 智能资源管理:自动化调度与负载均衡,最大化资源利用率。
  • 容错和弹性:支持任务自动重试、故障恢复及动态伸缩,确保高可用性并适应负载变化。
  • 高性能:利用共享内存和零拷贝技术,实现高效数据传输与计算。
  • 丰富生态集成:内置 Ray Tune(超参数调优)、Ray Serve(模型服务)和 Ray RLlib(强化学习)等库,并无缝对接 TensorFlow、PyTorch 等主流机器学习框架,支持复杂工作流。

凭借其强大特性,Ray 在众多计算密集型领域展现出卓越的适用性:

  • 机器学习和深度学习: 轻松实现分布式训练、超参数优化及模型部署,无缝对接常见深度学习框架,是大规模机器学习应用的理想选择。
  • 强化学习Ray RLlib 提供可扩展的强化学习库,支持广泛算法与环境,尤其适合需大规模并行仿真与训练的任务。
  • 数据分析和处理:高效执行分布式数据处理,轻松应对海量数据集,集成 Pandas、NumPy 等常用库,简化数据分析工作流。
  • 高性能计算:为科学计算、物理仿真、复杂建模等需要大规模并行处理和高吞吐的数据密集型应用提供强大算力支持。

3. Ray 的架构

image.png
Ray 的设计架构非常简洁,注重灵活性、可扩展性和高性能等方面,具体由以下几个部分组成:

  • Ray Core:

    • Task 和 Actor 模型:Ray 的核心并行计算原语。Task 用于执行无状态的函数调用,而 Actor 则代表有状态的、可独立运行的计算单元。
    • 调度器:集群的大脑,负责高效地调度和分配 TaskActor,确保系统的高可用性与高性能。
    • 资源管理器:全面追踪并管理集群内的计算资源(如 CPU、GPU),支持动态扩缩容和智能负载均衡,以优化资源利用。
  • Ray Cluster:

    • Head Node: 集群的主控单元,负责管理集群整体状态、调度任务,并协调各工作节点间的通信。
    • Worker Node:执行实际计算任务的节点,负责运行分配到的 TaskActor
    • Ray Dashboard:一个基于 Web 的用户界面,提供对 Ray 集群的实时监控与管理功能,用户可便捷查看集群状态、资源利用率、任务执行进度等信息。

4. Ray 的数据管理

Ray 在数据管理方面的设计是其高性能和易用性的关键。它通过创新的分布式对象存储和智能的对象引用机制,实现了数据在分布式环境中的高效流转与共享。

4.1 分布式共享内存对象存储

Ray 在集群的每个节点都维护了一个共享内存对象存储区,当 Task 或者 Actor 创建数据对象(如 NumPy数组、Pandas DataFrame 或自定义 Python 对象等)时,这些对象会被放到本地节点的共享内存中。
同一节点上的多个 Worker 进程可以直接访问共享内存中的对象,无需进行数据拷贝(零拷贝),极大提高了本地数据访问速度,当一个节点上的任务需要访问存储在另一个节点上的对象时, Ray 会自动且高效地将该对象传输到它需要的节点。
Ray 的对象存储它也能高效的管理大型数据对象和复杂的嵌套数据结构,同时,Ray 会自动跟踪对象的引用计数,当一个对象不再被任何 Task 或 Actor 引用时,它会被自动从对象存储中回收,释放内存资源。

4.2 对象引用

在 Ray 中,任务的输入和输出通常是对象引用(ObjectRef),而非数据对象本身,对象引用可以看作是指向存储在分布式对象存储中实际数据的轻量级指针或未来凭证(Future)。
Ray 的调度器利用这些对象引用来感知数据位置,它会尽可能的将依赖特定数据对象的任务调度到该节点上执行,从而最小化跨节点数据传输的开销。
在 Ray 中,对象引用自动构成了任务间的依赖关系图,一个任务只有在其所有输入对象引用都指向已完成计算的对象时,才会被调度执行,这个机制保证了执行顺序的正确性和数据的一致性。
同时,对象引用也支持容错机制,如果某个节点故障导致其上的对象丢失, Ray 可以利用任务的血缘关系(通过对象引用追踪)重新计算丢失的对象。
通过这些机制协同工作,Ray 不仅简化了分布式应用中复杂的数据共享和传递逻辑,还通过最大化局部性和最小化数据移动,为上层应用提供了强大的性能保障。

参考资料

  1. Getting Started with Distributed Machine Learning with PyTorch and Ray
  2. Ray Github Repo
  3. Ray Docs
评论区
头像
    头像
    JayNing
      

    膜拜 666