故障排除#
本页面包含已编译图执行的常见问题及解决方案。
限制#
已编译图是一项新功能,存在一些限制。
调用已编译图
只有编译已编译图的进程才能调用它。
已编译图的飞行中执行次数有一个最大限制。在使用 DAG API 时,如果在
dag.execute()时资源不足,Ray 会将任务排队以便稍后执行。Ray 已编译图目前不支持排队超出最大容量。因此,您可能需要在提交更多执行之前,使用ray.get()来消耗一些结果。作为一种临时解决方案,如果调用耗时过长,dag.execute()会抛出RayCgraphCapacityExceeded异常。未来,已编译图可能会有更好的错误处理和排队机制。
已编译图执行
理想情况下,您应尽量避免在 Actor 参与已编译图执行时在其上执行其他任务。已编译图任务将在 **后台线程** 上执行。提交给 Actor 的任何并发任务仍可以在主线程上执行,但您需要负责与已编译图后台线程进行同步。
目前,Actor 一次只能执行一个已编译图。要在同一 Actor 上执行另一个已编译图,您必须先拆解当前已编译图。有关更多详细信息,请参阅 返回 NumPy 数组。
传递和获取已编译图结果 (
CompiledDAGRef)已编译图的结果不能传递给另一个任务或 Actor。此限制将来可能会放宽,但目前它能实现更好的性能,因为后端确切地知道将结果推送到何处。
ray.get()在CompiledDAGRef上最多只能调用一次。如果对同一个CompiledDAGRef调用两次,将引发异常。这是因为结果的底层内存可能需要被重新用于未来的 DAG 执行。限制每个引用ray.get()的调用次数可以简化内存缓冲区的跟踪。如果
ray.get()返回的值是零拷贝反序列化的,那么相同 DAG 的后续执行将阻塞,直到该值在 Python 中超出作用域。因此,如果您持有ray.get()返回的零拷贝反序列化值,并且尝试执行高于最大并发度的已编译图,可能会导致死锁。这种情况将在未来被检测到,但目前您将收到一个RayChannelTimeoutError。有关更多详细信息,请参阅 在重新使用相同的 Actor 之前显式地拆解。
集体操作
对于 GPU 到 GPU 的通信,已编译图仅支持点对点传输。集体通信操作即将推出。
敬请关注 Ray 未来版本中的其他功能。
支持更好的 DAG 输入排队,以实现同一 DAG 的更多并发执行。
支持更多使用 NCCL 的集体操作。
支持在同一 Actor 上执行多个 DAG。
通用性能改进。
如果您遇到其他问题,或者有其他反馈或疑问,请在 GitHub 上提交 issue。如需查看已知问题的完整列表,请在 Ray GitHub 上查看标记为 compiled-graphs 的 issue。
返回 NumPy 数组#
Ray 在可能的情况下会零拷贝反序列化 NumPy 数组。如果您多次执行具有 NumPy 数组输出的已编译图,当一个先前已编译图执行的 NumPy 数组输出在尝试获取同一已编译图后续执行的结果之前未被删除时,您可能会遇到问题。这是因为 NumPy 数组会保留在已编译图的缓冲区中,直到您或 Python 删除它。建议显式删除 NumPy 数组,因为 Python 可能不会始终如您所料地立即垃圾回收 NumPy 数组。
例如,如果 NumPy 数组未被删除,以下代码示例可能会导致挂起或 RayChannelTimeoutError。
import ray
import numpy as np
from ray.dag import InputNode
@ray.remote
class NumPyActor:
def get_arr(self, _):
numpy_arr = np.ones((5, 1024))
return numpy_arr
actor = NumPyActor.remote()
with InputNode() as inp:
dag = actor.get_arr.bind(inp)
cgraph = dag.experimental_compile()
for _ in range(5):
ref = cgraph.execute(0)
result = ray.get(ref)
# Adding this explicit del would fix any issues
# del result
在前面的代码片段中,Python 可能不会在每次循环迭代时垃圾回收 result 中的 NumPy 数组。因此,在尝试获取后续已编译图执行的结果之前,您应该显式删除 NumPy 数组。
在重新使用相同的 Actor 之前显式地拆解#
如果您想重用已编译图的 Actor,在重用 Actor 之前显式地拆解已编译图非常重要。如果不显式地拆解已编译图,已编译图中为 Actor 创建的资源可能会与这些 Actor 的后续使用发生冲突。
例如,在以下代码中,Python 可能会延迟垃圾回收,从而触发第一个已编译图的隐式拆解。这可能会由于上述资源冲突导致段错误。
@ray.remote
class SendActor:
def send(self, x):
return x
actor = SendActor.remote()
with InputNode() as inp:
dag = actor.send.bind(inp)
cgraph = dag.experimental_compile()
# Not adding this explicit teardown before reusing `actor` could cause problems
# cgraph.teardown()
with InputNode() as inp:
dag = actor.send.bind(inp)
cgraph = dag.experimental_compile()