ray(一)_整体架构和任务调度

Ray整体架构

本文主要是对Ray Docs做的一点翻译

应用概念:

  • Task:进程上执行的单个函数调用。可以是无状态的(function.remote()),也可以是有状态的(Class.remote(),即actor)。Task是通过.remote()调用,是异步执行的,会返回objectRefs(结果数据的引用)。
  • Actor:有状态的worker进程,被@ray.remote()所装饰的类的实例。
  • Driver:根程序,运行ray.init()的程序。
  • Job:同一个Driver内的tasks, objects和actors的集合。

Ownership

每个worker进程管理并拥有它所提交的task和返回的objectRef(也就是结果数据不一定在执行函数的worker内,而是在提交task的worker内)

组件

Ray实例可以有多个worker节点,每个节点内部运行的进程如下:

  1. 一个或多个worker进程:用于提交和执行task,当然也可以执行actor的方法,前者worker进程是无状态,后者worker进程是有状态。每一个worker进程都会和一个具体的job绑定。默认初始化的worker进程数量等于CPU核心数量。每个worker会存储:
    1. ownership table:worker所引用的object的系统元数据(e.g. 引用数)
    2. in-process table:用于存储较小的object
  2. 一个raylet进程:raylet被同一集群上的所有job共享。raylet有两个线程:
    1. scheduler:负责分布式object store上的资源管理和满足task参数。集群中的各个scheduler共同构成了ray的distributed scheduler。
    2. shared-memory object store(即Plasma Object Store):负责存储和传输较大的object。集群中的各个object store共同构成了ray的distributed object store。

有一个特殊的worker节点也可以当作head节点,它除了开启上面的就进程,还会开启以下进程:

  1. **Global Control Store (GCS):**GCS是一个k/v存储服务器(用来存储系统级别的元数据,比如objects和actors的位置)。正在优化以使GCS运行多个节点上。
  2. **driver process:**driver是特殊的worker进程(执行最顶层应用的worker进程)。它可以提交task但不能执行。driver可以在任意节点上运行,但当运行了Ray autoscaler时是在head节点上

Task生命周期

task提交时,owner会等待依赖(比如task function的参数)。依赖可以在来自集群的任意节点。依赖一旦准备好,owner会从scheduler请求资源。资源如果可用,scheduler会同意请求,并会携带worker地址信息响应给owner,这个worker用来执行task。

owner通过gRPC将task发送给worker,worker执行完task后会存储结果:

  1. 如果结果很小(默认是小于100KiB),就会返回给owner,owner会存储到in-process table。
  2. 如果结果比较大,worker会将结果存储在它本地的Plasma Object Store,并告诉owner:object已经在分布式内存中了,允许owner引用。

如果task提交时,参数是一个objectRef,那在执行该task前必须先处理参数:

  1. 如果参数很小,直接从owner的in-process object store复制到task description,worker可以直接引用。
  2. 如果参数很大,那就必须从Plasma Object Store中取,scheduler会辅助object的传输:查找object的位置并在不同节点中复制。

Actor生命周期

actor存活时间和元数据都是存储在GCS中,每个actor客户端可以缓存这些元数据在本地,然后通过gRPC根据元数据将task发送给其它actor。

actor的创建:创建actor的worker进程首先会在GCS中同步注册acotr。一旦GCS响应,那么woker进程注册actor的过程就是异步的,这和function.remote()是一样的。如果创建actor的依赖都被满足,创建者就会将task规范(?)发送给GCS,GCS就会通过分布式调度协议(distributed scheduling protocol)调度actor creation task(类似于task的调度,GCS可以比作actor creation task的owner)。与此同时,Class.remote()会立刻返回actor handle。

因为actor在创建时已经调度了资源,在执行actor内的方法时,就不需要再通过scheduler调度资源

Task任务调度和Object存储的实例

以下面的代码为例:

@ray.remote 
def A(): 
    y_id = C.remote(B.remote()) 
    y = ray.get(y_id)

task A会提交task B和task C,task C是依赖task B的结果Object作为参数的。这里假设B的结果为large object X,也就是采用plasma store(共享内存存储);而C的结果为small object Y,采用进程内存储(in-process table)。

task scheduling

task sche.png

Node1执行task A,那么B,C由它提交,Node1的ownership table就会保存B C的结果X Y的条目(并不是具体的值)。然后开始看task B的调度过程:

  1. worker1(Node1)会向local scheduler(in the raylet process) 请求资源执行B;
  2. local scheduler会对该请求响应(这里假设的是worker1本地资源不足),本地调度器告诉worker1再向Node2的调度器发起请求;
  3. worker1就会更新自己的ownership table表明B()由Node2执行;
  4. worker1向Node2的调度器(Scheduler 2)发起请求;
  5. Scheduler 2同意分配资源,向Node1返回Node2的地址。Scheduler 2会保证worker 1占用这些资源时,不会被分配给其它tasks;
  6. worker 1发送task B给worker 2执行。

task execution

task exec.png

这部分展示worker 2执行任务并返回给owner(worker 1)存储值的过程:

  1. worker 2执行完task B之后,会将X存储在自己的shared-memory object store(即Plasma Object Store),这是因为X为large;
    1. Node 2异步更新object table表示X再自己这(虚线箭头);
    2. Node 2会一直保存X知道Node 1通知它删除(图中没展示)。
  2. Worker 2响应给worker 1告诉它B已经执行完成了;
  3. Worker 1更新自己的ownership table中的Val为引用,表示X存储再共享内存中;
  4. Worker 1返回资源给scheduler 2(就是放弃占用的资源)。

Distributed task scheduling and argument resolution

arg solu.png

B执行完了后,参数就准备好了。worker 1现在就要准备调度C

  1. 同调度task B
  2. 同调度task B
  3. 同调度task B
  4. 同调度task B
  5. scheduler 3看到task C需要参数X,但是本地没有X的副本,就会将task C放进队列,并向object table询问X的定位。

arg solu 2.png

接上,该图是Node 3获取X的过程:

  1. Object table响应scheduler 3 请求,告诉它X在N2;
  2. scheduler 3向N2的object store请求X的副本;
  3. X被复制到N3;
    • N3也会异步更新Object Table,表明X的副本也在N3上;
    • N3的X会被缓存但不会保证不被删除。因为X现在有多个副本保存在各个节点上,N3如果内存有压力,可以根据LRU算法淘汰本地的X副本。
  4. N3现在满足了task C的依赖,可以分配资源给worker 1执行task C,返回N3的地址给N1;

task C Y.png
  1. worker 1发送task C给worker 3执行;
  2. worker 3从本地object store获取X,执行C(X);
  3. worker 3执行完毕,返回Y给worker 1的ownership table
  4. 因为Y所占内存比较小,会存储在worker 1的in-process table中;并且ownership table会删除task C的描述和位置,因为该任务已经执行完毕。此时y = ray.get(y_id)就可以获得Y的值
  5. worker 1将N3的资源放弃。

Garbage collection

garbage.png

这里展示垃圾回收机制:

  1. worker 1会擦除X,这是因为只有C对X有引用,此时C已经结束了。但是会保存Y,因为应用还在引用Y的ID;

    最终所有X的副本都将删除。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值