反模式:使用全局变量在任务和 Actor 之间共享状态#
TLDR: 不要使用全局变量在任务和 Actor 之间共享状态。相反,将全局变量封装在 Actor 中,并将 Actor 句柄传递给需要修改或访问状态的其他任务和 Actor。
Ray driver、任务和 Actor 运行在不同的进程中,因此它们不共享相同的地址空间。这意味着如果您在一个进程中修改全局变量,这些更改不会反映在其他进程中。
解决方案是使用 Actor 的实例变量来持有全局状态,并将 Actor 句柄传递给需要修改或访问状态的地方。请注意,不支持使用类变量在同一类的不同实例之间管理状态。每个 Actor 实例都在自己的进程中实例化,因此每个 Actor 都将拥有自己的类变量副本。
代码示例#
反模式
import ray
ray.init()
global_var = 3
@ray.remote
class Actor:
def f(self):
return global_var + 3
actor = Actor.remote()
global_var = 4
# This returns 6, not 7. It is because the value change of global_var
# inside a driver is not reflected to the actor
# because they are running in different processes.
assert ray.get(actor.f.remote()) == 6
更好的方法
@ray.remote
class GlobalVarActor:
def __init__(self):
self.global_var = 3
def set_global_var(self, var):
self.global_var = var
def get_global_var(self):
return self.global_var
@ray.remote
class Actor:
def __init__(self, global_var_actor):
self.global_var_actor = global_var_actor
def f(self):
return ray.get(self.global_var_actor.get_global_var.remote()) + 3
global_var_actor = GlobalVarActor.remote()
actor = Actor.remote(global_var_actor)
ray.get(global_var_actor.set_global_var.remote(4))
# This returns 7 correctly.
assert ray.get(actor.f.remote()) == 7