带外通信#

通常,Ray actor 的通信通过 actor 方法调用完成,数据通过分布式对象存储共享。但是,在某些用例中,带外通信可能很有用。

封装库进程#

许多库已经拥有成熟、高性能的内部通信堆栈,并将 Ray 作为语言集成的 actor 调度器。actor 之间的实际通信大部分是通过现有的通信堆栈以带外方式完成的。例如,Horovod-on-Ray 使用 NCCL 或基于 MPI 的集体通信,RayDP 使用 Spark 的内部 RPC 和对象管理器。有关更多详细信息,请参阅 Ray 分布式库模式

Ray Collective

Ray 的集体通信库(ray.util.collective)允许在分布式 CPU 或 GPU 之间进行高效的带外集体和点对点通信。有关更多详细信息,请参阅 Ray Collective

HTTP 服务器#

您可以在 actor 中启动一个 HTTP 服务器,并向客户端公开 HTTP 端点,以便 Ray 集群外部的用户可以与 actor 进行通信。

import ray
import asyncio
import requests
from aiohttp import web


@ray.remote
class Counter:
    async def __init__(self):
        self.counter = 0
        asyncio.get_running_loop().create_task(self.run_http_server())

    async def run_http_server(self):
        app = web.Application()
        app.add_routes([web.get("/", self.get)])
        runner = web.AppRunner(app)
        await runner.setup()
        site = web.TCPSite(runner, "127.0.0.1", 25001)
        await site.start()

    async def get(self, request):
        return web.Response(text=str(self.counter))

    async def increment(self):
        self.counter = self.counter + 1


ray.init()
counter = Counter.remote()
[ray.get(counter.increment.remote()) for i in range(5)]
r = requests.get("http://127.0.0.1:25001/")
assert r.text == "5"

同样,您也可以公开其他类型的服务器(例如,gRPC 服务器)。

限制#

当使用带外通信与 Ray actors 进行交互时,请记住 Ray 不会管理 actor 之间的调用。这意味着分布式引用计数等功能将无法与带外通信配合使用,因此您应注意不要通过这种方式传递对象引用。