反模式:闭包捕获大对象损害性能#

简而言之:避免在远程函数或类中通过闭包捕获大对象,而是使用对象存储。

定义 ray.remote 函数或类时,很容易意外地在定义中隐式捕获大对象(大于几 MB)。这可能导致性能下降甚至 OOM,因为 Ray 并不设计用于处理非常大的序列化函数或类。

对于这些大对象,有两种解决方案:

  • 使用 ray.put() 将大对象放入 Ray 对象存储中,然后将对象引用作为参数传递给远程函数或类(下文的“更好的方法 #1”)。

  • 通过传递 lambda 方法在远程函数或类内部创建大对象(“更好的方法 #2”)。这也是使用不可序列化对象的唯一选择。

代码示例#

反模式

import ray
import numpy as np

ray.init()

large_object = np.zeros(10 * 1024 * 1024)


@ray.remote
def f1():
    return len(large_object)  # large_object is serialized along with f1!


ray.get(f1.remote())

更好的方法 #1

large_object_ref = ray.put(np.zeros(10 * 1024 * 1024))


@ray.remote
def f2(large_object):
    return len(large_object)


# Large object is passed through object store.
ray.get(f2.remote(large_object_ref))

更好的方法 #2

large_object_creator = lambda: np.zeros(10 * 1024 * 1024)  # noqa E731


@ray.remote
def f3():
    large_object = (
        large_object_creator()
    )  # Lambda is small compared with the large object.
    return len(large_object)


ray.get(f3.remote())