Ray: Scheduling and Actor placement

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011254180/article/details/83345689

Ray是面向增强学习场景的分布式计算框架,相关介绍参考博客

本篇文章主要对 Ray中 remote函数的调度以及 Actor抽象的放置进行介绍。

一、Remote函数的调度

1. Remote函数的定义

Remote函数时Ray分布式计算中的核心概念,一般如下所示:

@ray.remote
def add(a, b):
    return a + b

id_c = add.remote(a, b)
c = ray.get(id_c)

2. Remote函数的执行

由上不难发现,Remote函数定义与普通的Python函数定义非常相似,只是多了@ray.remote装饰器。那么它具体执行时和普通函数有什么区别呢?

Ray采取的是自下而上的分布式调度器,当提交任务到worker节点时,首先由节点的local scheduler进行调度,在本节点运行,当本地节点不能满足运行的条件时,将任务推送到global scheduler由其调度。那么Raylocal scheduler是怎样判断是否该调度到本地节点还是上推到global scheduler呢?

  • local scheduler会维护一个任务队列(task queue),每次调度任务时它会检查当前任务队列的长度,如果超过一定的阈值,那么认为本机过载了,不在调度当前任务而是将其转给上层全局调度器。
  • remote函数缺少运行时所需的资源,如gpu资源。
  • remote函数的输入值是远程的。

3. Remote函数简单调度示例

下图为论文中提供的简单示例,用来说明remote函数的输入值是远程时如何调度。

如图,a与b分布存储在节点N1和N2上,driver将任务提交给local scheduler后,由于b不存在于N1中,即remote函数的输入是远程的,推送至global scheduler由其调度。上图将其分发到节点N2去执行,其实也有可能分发到N1去执行,那么就是N1到N2将对象b拉取到本地,这依赖于global scheduler的调度策略,目前其采取均匀分布策略。调度策略相关代码

二、Actor抽象的放置

Ray中的远程函数为我们提供分布式函数编程,但在实践中会受到一些限制,所有Ray中又引入actor抽象扩展数据流模型。对于Actor抽象不了解的可以参考博客

1. Actor的定义和创建

如下,装饰器 @ray.remote表明类Counter实例化后为actor

@ray.remote
class Counter(object):
    def __init__(self):
        self.value = 0
 
    def increment(self):
        self.value += 1
        return self.value

为了真正创建一个actor,我们通过调用Counter.remote()来实例化该类。

a1 = Counter.remote()
a2 = Counter.remote()

2. Actor的放置策略

目前,actor的放置是随机的,只能保证一点,如果现在有20台机器,且gpu共有50个,此时我们创建了50个actor,每个actor需要一个gpu,此时创建的50个actor会与50个gpu一一对应,分布在20台机器上。

另一种情况,现有2台机器,每台机器有10个gpu,创建10个actor且每个actor需要一个gpu,那么可能出现10个actor创建在一台机器上或者每台机器上创建5个actor等等情况。

针对上述情况,Ray提供一个方法可以指定actor在哪一台机器上运行,即每台机器启动时可以创建自己特有的资源,当创建actor时,指定需要特有的资源,则此时actor的创建就受控制,具体参考下节。

3. Actor的指定放置方法

首先启动节点时,提供特有的节点资源,如节点N1为head节点,N2为非head节点,N1启动时指定特殊的资源,如下:

ray start --head --resources='{"Resource1": 4}'

其中Resource1可以任意写,如写A也行,N2此时正常连接至头结点就行。

当我们创建actor时只需如下就行:

@ray.remote(resources={'Resource1': 1})
class Counter(object):
    def __init__(self):
        self.value = 0
 
    def increment(self):
        self.value += 1
        return self.value

此时创建的actor只会在节点N1上,因为所需的资源Resource1只有N1拥有。

猜你喜欢

转载自blog.csdn.net/u011254180/article/details/83345689
今日推荐