反模式:在任务参数上调用 ray.get 会损害性能#

简而言之:如果可能,请将 ObjectRefs 作为直接任务参数传递,而不是将列表作为任务参数传递,然后在任务内部调用 ray.get()

当任务调用 ray.get() 时,它必须阻塞直到 ObjectRef 的值准备就绪。如果所有核心都已占用,这种情况可能导致死锁,因为生成 ObjectRef 值的任务可能需要调用任务的资源才能运行。为了处理此问题,如果调用任务会在 ray.get() 中阻塞,Ray 会暂时释放调用者的 CPU 资源,以允许待处理的任务运行。这种行为可能会损害性能和稳定性,因为调用者会继续使用一个进程和内存来保存其堆栈,而其他任务正在运行。

因此,如果可能,最好将 ObjectRefs 作为直接参数传递给任务,并避免在任务内部调用 ray.get

例如,在以下代码中,首选后者调用依赖任务的方法。

import ray
import time


@ray.remote
def f():
    return 1


@ray.remote
def pass_via_nested_ref(refs):
    print(sum(ray.get(refs)))


@ray.remote
def pass_via_direct_arg(*args):
    print(sum(args))


# Anti-pattern: Passing nested refs requires `ray.get` in a nested task.
ray.get(pass_via_nested_ref.remote([f.remote() for _ in range(3)]))

# Better approach: Pass refs as direct arguments. Use *args syntax to unpack
# multiple arguments.
ray.get(pass_via_direct_arg.remote(*[f.remote() for _ in range(3)]))

在嵌套任务中避免 ray.get 并不总是可能的。调用 ray.get 的一些有效理由包括: