将 ActorHandler 保存在另一个 actor 中供以后使用时发生错误
Error happens when keeping an `ActorHandler` in another actor for later use
我想要一个遥控器 class 保留另一个遥控器 class 以便以后可以调用它。下面的代码提供了一个例子
import ray
ray.init()
@ray.remote
class Worker:
def __init__(self):
self.a = 1
self.l = None
def set(self, learner):
self.l = learner
def step(self):
x = ray.get(self.l.p.remote(self.a))
return x
@ray.remote
class Learner:
def __init__(self):
self.a = 3
def step(self, worker):
print(ray.get(worker.step.remote()))
def p(self, a):
return a + self.a
l = Learner.remote()
w = Worker.remote()
w.set.remote(l)
ray.get(l.step.remote(w))
ray.shutdown()
然而,这段代码不起作用;它卡住了而没有发出任何错误。我知道问题的根源来自Worker
中的step
函数,但我不知道为什么会出错,也不知道如何解决。
首先,请注意 ray.get
是一个阻塞调用。这意味着您的程序将被阻塞,并且在 ray.get
函数成功之前无法转到下一行代码。 (您可以通过向 remote
函数添加 timeout
参数来防止这种情况发生)。
发生这种情况是因为 l
被阻止,直到 worker.step.remote
完成 (ray.get(worker.step.remote()
)。当调用 worker.step
方法时,它会尝试调用 l.p.remote
。由于 ray.get(self.l.p.remote(self.a)
,w
将被阻塞,直到 l.p
完成。但是正如您所看到的,l
被阻止并且不能 运行 任何代码。这意味着 l.p
永远不会 运行 直到 l.step
完成。这是一个简单的图表供您理解。
现在两个工人都被阻止了,l.step.remote
永远不会完成。这意味着您的驱动程序(Python 脚本)也被阻止了。
结果整个程序挂了!!
那这个问题怎么解决呢?
首先,我强烈建议您不要使用两个演员 类 互相等待的模式。这通常是一个糟糕的模式,即使您正在编写其他程序也是如此。当程序是多线程或者异步的时候可以解决这个问题
如果你真的需要使用这个模式,你可以使用async actor。异步 actor 使用 await
而不是 ray.get
,并且每个 actor 都不会被阻塞,因为它们 运行ning 作为协程。
https://ray.readthedocs.io/en/latest/async_api.html
EX)
import ray
ray.init()
@ray.remote
class Worker:
def __init__(self):
self.a = 1
self.l = None
def set(self, learner):
self.l = learner
async def step(self):
x = await self.l.p.remote(self.a)
return x
@ray.remote
class Learner:
def __init__(self):
self.a = 3
async def step(self, worker):
print(await worker.step.remote())
async def p(self, a):
return a + self.a
l = Learner.remote()
w = Worker.remote()
w.set.remote(l)
await l.step.remote(w)
# ray.shutdown()
我想要一个遥控器 class 保留另一个遥控器 class 以便以后可以调用它。下面的代码提供了一个例子
import ray
ray.init()
@ray.remote
class Worker:
def __init__(self):
self.a = 1
self.l = None
def set(self, learner):
self.l = learner
def step(self):
x = ray.get(self.l.p.remote(self.a))
return x
@ray.remote
class Learner:
def __init__(self):
self.a = 3
def step(self, worker):
print(ray.get(worker.step.remote()))
def p(self, a):
return a + self.a
l = Learner.remote()
w = Worker.remote()
w.set.remote(l)
ray.get(l.step.remote(w))
ray.shutdown()
然而,这段代码不起作用;它卡住了而没有发出任何错误。我知道问题的根源来自Worker
中的step
函数,但我不知道为什么会出错,也不知道如何解决。
首先,请注意 ray.get
是一个阻塞调用。这意味着您的程序将被阻塞,并且在 ray.get
函数成功之前无法转到下一行代码。 (您可以通过向 remote
函数添加 timeout
参数来防止这种情况发生)。
发生这种情况是因为 l
被阻止,直到 worker.step.remote
完成 (ray.get(worker.step.remote()
)。当调用 worker.step
方法时,它会尝试调用 l.p.remote
。由于 ray.get(self.l.p.remote(self.a)
,w
将被阻塞,直到 l.p
完成。但是正如您所看到的,l
被阻止并且不能 运行 任何代码。这意味着 l.p
永远不会 运行 直到 l.step
完成。这是一个简单的图表供您理解。
现在两个工人都被阻止了,l.step.remote
永远不会完成。这意味着您的驱动程序(Python 脚本)也被阻止了。
结果整个程序挂了!!
那这个问题怎么解决呢?
首先,我强烈建议您不要使用两个演员 类 互相等待的模式。这通常是一个糟糕的模式,即使您正在编写其他程序也是如此。当程序是多线程或者异步的时候可以解决这个问题
如果你真的需要使用这个模式,你可以使用async actor。异步 actor 使用 await
而不是 ray.get
,并且每个 actor 都不会被阻塞,因为它们 运行ning 作为协程。
https://ray.readthedocs.io/en/latest/async_api.html
EX)
import ray
ray.init()
@ray.remote
class Worker:
def __init__(self):
self.a = 1
self.l = None
def set(self, learner):
self.l = learner
async def step(self):
x = await self.l.p.remote(self.a)
return x
@ray.remote
class Learner:
def __init__(self):
self.a = 3
async def step(self, worker):
print(await worker.step.remote())
async def p(self, a):
return a + self.a
l = Learner.remote()
w = Worker.remote()
w.set.remote(l)
await l.step.remote(w)
# ray.shutdown()