Python: разница между * args и списком в удаленной функции - PullRequest
0 голосов
/ 21 января 2019

Определить список

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)) неподдерживаемые типы операндов для +: 'common.ObjectID' и '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

1 Ответ

0 голосов
/ 21 января 2019

Когда аргументы передаются в удаленную функцию 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 s.

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)'
...