Ray相关知识01

一、Ray 的基础结构

Ray的架构由应用层和系统层组成,其中应用层实现了Ray的API,作为前端供用户使用,而系统层则作为后端来保障Ray的高可扩展性和容错性。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z6ODnK0o-1677833811760)(C:\Users\13064\AppData\Roaming\Typora\typora-user-images\image-20230226145146836.png)]

应用层

应用层中有三种类型的进程:

驱动器进程 (Driver Process):

执行用户程序的进程。顾名思义,所有操作都需要由主进程来驱动。

工作器进程 (Worker Process):

​ 执行由驱动器或其他工作器调用的任务(远程函数)的无状态的进程。工作器由系统层分配任务并自动启动。当声明一个远程函数时,该函数将被自动发送到所有的工作器中。在同一个工作器中,任务是串行地执行的,工作器并不维护其任务与任务之间的局部状态,即在工作器中,一个远程函数执行完后,其局部作用域的所有变量将不再能被其他任务所访问。

行动器进程 (Actor Process):

​ 行动器被调用时只执行其所暴露的方法。行动器由工作器或驱动器显式地进行实例化。与工作器相同的是,行动器也会串行地执行任务,不同的是行动器上执行的每个方法都依赖于其前面所执行的方法所导致的状态。

@ray.remote
def f(x):
    # ==== 工作器进程 ====
    return x * x

@ray.remote
class Counter(object):
    def __init__(self):
        # ==== 行动器进程 ====
        self.value = 0

    def increment(self):
        # ==== 行动器进程 ====
        self.value += 1
        return self.value

if __name__ == "__main__":
    # ==== 驱动器进程 ====
    object_ref = f.remote(2)
    assert ray.get(object_ref) == 4

    counter = Counter.remote()
    refs = []
    for i in range(10):
        ref = counter.increment.remote()
        refs.append(ref)
    for i, ref in enumerate(refs):
        assert ray.get(ref) == i + 1

系统层

系统层由三个主要部件组成:全局控制存储器 (Global Control Store)、分布式调度器 (Distributed Scheduler)和分布式对象存储器 (Distributed Object Store)。

全局控制器(GCS):

​ 对象表 (Object Table):记录每个对象存在于哪些节点

​ 任务表 (Task Table):记录每个任务运行于哪个节点

​ 函数表 (Function Table):记录用户进程中定义的远程函数

​ 事件日志 (Event Logs):记录任务运行日志

分布式调度器:

分为全局调度器和局部调度器,为了避免全局调度器负载过重,在节点创建的任务首先被提交到局部调度器,如果该节点没有过载且节点资源能够满足任务的需求(如GPU的需求),则任务将在本地被调度,否则任务才会被传递到全局调度器。

下图展示了Ray的调度过程,箭头的粗细表示过程发生频率的高低。用户进程和工作器向本地调度器提交任务,大多数情况下,任务将在本地被调度。少数情况下,局部调度器会向全局调度器提交任务,并向GCS传递任务的相关信息,将任务涉及的对象和函数存入全局的对象表和函数表中,然后全局调度器会从GCS中读取到信息,并选择在其他合适的节点上调度这一任务。更具体地来说,全局调度器会根据任务的请求选出具有足够资源的一系列节点,并在这些节点中选出等待时间最短的一个节点。

分布式对象存储器
任务定义、提交和执行过程

在这里插入图片描述

\0. 【定义远程函数】位于 N1的用户程序中定义的远程函数add被装载到GCS的函数表中,位于N2的工作器从GCS中读取并装载远程函数add
1.N【提交任务】位于N1的用户程序向本地调度器提交add(a,b)的任务
2.N【提交任务到全局】本地调度器将任务提交至全局调度器
3.N【检查对象表】全局调度器从GCS中找到add任务所需的实参a,b,发现a在N1上,b在N2上(a,b已在用户程序中事先定义)
4.N【执行全局调度】由上一步可知,任务的输入平均地分布在两个节点,因此全局调度器随机选择一个节点进行调度,此处选择了N2
5.N【检查任务输入】N2的局部调度器检查任务所需的对象是否都在N2的本地对象存储器中
6.N【查询缺失输入】N2的局部调度器发现任务所需的a不在N2中,在GCS中查找后发现a在N1中
7.N【对象复制】将a从N1复制到N2
8.N【执行局部调度】在N2的工作器上执行add(a,b)的任务
9.N【访问对象存储器】add(a,b)访问局部对象存储器中相应的对象

获取任务执行结果过程

\1. 【提交get请求】向本地调度器提交ray.get的请求,期望获取add任务执行的返回值
\2. 【注册回调函数】N1本地没有存储返回值,所以根据返回值对象的引用id_c在GCS的对象表中查询该对象位于哪个节点,假设此时任务没有执行完成,那么对象表中找不到id_c,因此N1的对象存储器会注册一个回调函数,当GCS对象表中出现id_c时触发该回调,将c从对应的节点复制到N1上
\3. 【任务执行完毕】N2上的add任务执行完成,返回值c被存储到N2的对象存储器中
\4. 【将对象同步到GCS】N2将c及其引用id_c存入GCS的对象表中
\5. 【触发回调函数】步骤2中注册的回调函数被触发
\6. 【执行回调函数】将c从N2复制到N1
\7. 【返回用户程序】将c返回给用户程序,任务结束

二、Raylet 本地调度的核心

全局控制器和worker的关系图

在这里插入图片描述

Raylet 在中间的作用非常关键,Raylet 包含了几个重要内容:

  • Node Manager:主要是通信的连接和消息处理管理
  • Object Manager:Object Store 的管理
  • gcs_client :gcs_client 是连接 GCS 客户端。

三、Ray Core

Ray Tasks和Ray Actors / 任务(Task)和行动器(Actor)

Ray Task

任务是指在无状态的工作器中执行的远程函数。远程函数被调用时会立即返回一个future对象,而真正的返回值可以通过ray.get(<future对象>)的方式来获取。这样的编程模型既允许用户编写并行计算代码,同时又提醒用户要关注数据之间的依赖性。任务是无状态的,任务所操作的对象都可以看作不可变对象(Immutable Objects),或者任务调用可以看作一个无副作用的(Side-effect Free)表达式,任务的输出(返回值)仅与输入(实参)有关。

import ray
ray.init()
# @ray.remote将f函数变成了一个Ray Task
@ray.remote
def f(x):
    return x * x

futures = [f.remote(i) for i in range(4)]
print(ray.get(futures)) # [0, 1, 4, 9]

Ray Actor

行动器方法的调用可能会修改行动器的状态,而这一状态可能会影响后续方法的调用,因此同一行动器下的方法需要按照提交顺序串行地调用。

行动器用来表达有状态的计算任务。每个行动器都会暴露一些可供远程调用的方法,类似于任务中的远程函数,不同的是,使用f.remote顺序地提交若干个远程函数后,这些函数是并行执行的,**但在同一个actor下使用actor.method.remote顺序地提交若干个远程方法后,这些方法将串行地执行。**但是,不同actor之间的调用是可以并行的。可以用一个图来描述任务和行动器的区别和联系:

import ray
ray.init() # Only call this once.

@ray.remote
class Counter(object):
    def __init__(self):
        self.n = 0

    def increment(self):
        self.n += 1

    def read(self):
        return self.n

counters = [Counter.remote() for i in range(4)]
[c.increment.remote() for c in counters]
futures = [c.read.remote() for c in counters]
print(ray.get(futures)) # [1, 1, 1, 1]

Ray API

ray.init():初始化您的 Ray 集群。传入一个地址以连接到现有的集群。

@ ray. remote: 将函数转换为Tasks,将类转换为Actors。

ray.put():将值放入 Ray 的对象存储中。

ray.get () : 从对象存储获取 values。返回您放在那里的值或由任务或参与者计算的值。

.remote () : 在 Ray 集群上运行 Actor 方法或任务,用于实例化 Actor。

ray.wait () : 返回两个对象引用列表,一个包含我们正在等待的已完成的任务,另一个包含未完成的任务

四、Ray 库

datasets:数据预处理,数据预处理是将原始数据转换为机器学习模型特征的常用技术。

Training:用来模型的分布式训练,

Tuning:进行超参数调优,集成了多种超参优化方法

​ 1.能够在不到 10 行代码中启动多节点分布式超参数扫描。

​ 2.支持包括 PyTorch 在内的所有主流机器学习框架。
​ 3.对 GPU 的一流支持。
​ 4.自动管理检查点并将日志记录到 TensorBoard。
​ 5.访问最先进的算法,如基于群体的训练(PBT)、BayesOptSearch、HyperBand/ASHA。

scoring:

serving:可扩展的模型服务库,特别适合模型组合,能够构建由多个 ML 模型和业务逻辑组成的复杂推理服务

基于群体的训练(PBT)、BayesOptSearch、HyperBand/ASHA。

serving:可扩展的模型服务库,特别适合模型组合,能够构建由多个 ML 模型和业务逻辑组成的复杂推理服务

RL:是一个用于强化学习的库,RLlib不会自动安装深度学习的库,但是支持TensorFlow和Pytorch。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值