Python: 远程函数中 *args 和 list 的区别
Python: difference between *args and list in a remote function
定义一个列表
g = [1, 2, 3, 4]
版本 1
@ray.remote
def f(*g):
return np.mean(g, axis=0)
f_ids = [f.remote(*g) for _ in range(10)]
print(ray.get(f.remote(*f_ids)))
版本 2
@ray.remote
def f(g): # g is object ID list
return np.mean(g, axis=0)
f_ids = [f.remote(g) for _ in range(10)]
print(ray.get(f.remote(f_ids)))
第一个代码工作正常,但是版本 2 不工作。错误信息是
ray.get(f.remote(f_ids))
unsupported operand type(s) for +: 'common.ObjectID' and 'common.ObjectID'
我想做像版本 2 这样的事情的原因是我实际上想做像下面这样的事情
@remote
def f(g1, g2): # g1 and g2 are object ID lists
... # do something here
我不知道如何将 g1
和 g2
设为 *g1
和 *g2
所以我想出了版本 2。为什么版本 2 不起作用?我该如何解决?
参考代码在这里
https://ray.readthedocs.io/en/latest/example-parameter-server.html#synchronous-parameter-server
当将参数传递给 Ray 远程函数时,任何类型为 ray.ObjectID
的参数都会自动替换为解压缩后的值(这意味着 ray.get
在后台被调用)。所有其他参数不变。
这就是为什么如果你定义一个像
这样的远程函数
# Assuming you already called "import ray" and "ray.init()".
@ray.remote
def g(x):
print(x)
你会看到
g.remote(1) # This prints '1'
g.remote(ray.put(1)) # This also prints '1'
g.remote([ray.put(1)]) # This prints '[ObjectID(feffffffe3f2116088b37cb305fbb2537b9783ee)]'
第三行,因为参数是一个列表,所以列表里面的ObjectID
没有被它对应的值替换。
在你的例子中,你有
@ray.remote
def f(*xs):
print(xs)
您的版本 1 和您的 版本 2 之间的区别在于 版本 1 ,您正在传递多个 ObjectID
个参数。在 版本 2 中,您将传入一个参数,该参数是一个包含多个 ObjectID
的列表。
xs = [ray.put(1), ray.put(2)]
f.remote(*xs) # This prints '(1, 2)'
f.remote(xs) # This prints '([ObjectID(fcffffffe3f2116088b37cb305fbb2537b9783ee), ObjectID(fbffffffe3f2116088b37cb305fbb2537b9783ee)],)'
为了做你想做的事,你可能需要做这样的事情(本质上是将两个列表合并为一个)。它不是最漂亮的,但它应该可以工作。
@ray.remote
def h(num_xs, *xs_and_ys):
xs = xs_and_ys[:num_xs]
ys = xs_and_ys[num_xs:]
print(xs, ys)
x_ids = [ray.put(1), ray.put(2)]
y_ids = [ray.put(3), ray.put(4), ray.put(5)]
h.remote(len(x_ids), *(x_ids + y_ids)) # This prints '(1, 2) (3, 4, 5)'
定义一个列表
g = [1, 2, 3, 4]
版本 1
@ray.remote
def f(*g):
return np.mean(g, axis=0)
f_ids = [f.remote(*g) for _ in range(10)]
print(ray.get(f.remote(*f_ids)))
版本 2
@ray.remote
def f(g): # g is object ID list
return np.mean(g, axis=0)
f_ids = [f.remote(g) for _ in range(10)]
print(ray.get(f.remote(f_ids)))
第一个代码工作正常,但是版本 2 不工作。错误信息是
ray.get(f.remote(f_ids)) unsupported operand type(s) for +: 'common.ObjectID' and 'common.ObjectID'
我想做像版本 2 这样的事情的原因是我实际上想做像下面这样的事情
@remote
def f(g1, g2): # g1 and g2 are object ID lists
... # do something here
我不知道如何将 g1
和 g2
设为 *g1
和 *g2
所以我想出了版本 2。为什么版本 2 不起作用?我该如何解决?
参考代码在这里 https://ray.readthedocs.io/en/latest/example-parameter-server.html#synchronous-parameter-server
当将参数传递给 Ray 远程函数时,任何类型为 ray.ObjectID
的参数都会自动替换为解压缩后的值(这意味着 ray.get
在后台被调用)。所有其他参数不变。
这就是为什么如果你定义一个像
这样的远程函数# Assuming you already called "import ray" and "ray.init()".
@ray.remote
def g(x):
print(x)
你会看到
g.remote(1) # This prints '1'
g.remote(ray.put(1)) # This also prints '1'
g.remote([ray.put(1)]) # This prints '[ObjectID(feffffffe3f2116088b37cb305fbb2537b9783ee)]'
第三行,因为参数是一个列表,所以列表里面的ObjectID
没有被它对应的值替换。
在你的例子中,你有
@ray.remote
def f(*xs):
print(xs)
您的版本 1 和您的 版本 2 之间的区别在于 版本 1 ,您正在传递多个 ObjectID
个参数。在 版本 2 中,您将传入一个参数,该参数是一个包含多个 ObjectID
的列表。
xs = [ray.put(1), ray.put(2)]
f.remote(*xs) # This prints '(1, 2)'
f.remote(xs) # This prints '([ObjectID(fcffffffe3f2116088b37cb305fbb2537b9783ee), ObjectID(fbffffffe3f2116088b37cb305fbb2537b9783ee)],)'
为了做你想做的事,你可能需要做这样的事情(本质上是将两个列表合并为一个)。它不是最漂亮的,但它应该可以工作。
@ray.remote
def h(num_xs, *xs_and_ys):
xs = xs_and_ys[:num_xs]
ys = xs_and_ys[num_xs:]
print(xs, ys)
x_ids = [ray.put(1), ray.put(2)]
y_ids = [ray.put(3), ray.put(4), ray.put(5)]
h.remote(len(x_ids), *(x_ids + y_ids)) # This prints '(1, 2) (3, 4, 5)'