远程调用时传入的函数指针必须是远程函数
- 在 Ray 中不支持直接传入 local 函数指针作为远程函数的执行对象,需通过 Ray 装饰器(
@ray.remote)将函数注册为远程可执行,再通过函数名.remote()调用(本质是基于函数标识而非指针传递) - 总结:
- 不推荐将普通函数作为参数传递给 Ray 远程函数
- 推荐使用
@ray.remote装饰器或在远程函数内部定义逻辑 - 注意:一些代码在单机环境下可能碰巧能运行,但不具有可移植性和可靠性(这一点需要注意 Ray 本地调试通过可能也无法分布式运行)
错误示例(未注册本地函数)
若
add未被@ray.remote注册,它只是一个本地函数 ,无法在 Ray 分布式环境中执行,直接传递给远程函数(如execute_func)会报错1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23import ray
ray.init(ignore_reinit_error=True)
# 未注册的本地函数
def add(a, b):
return a + b
# 已注册的远程函数
def execute_func(func, x, y):
# 此处调用本地函数会失败,因为 func 在远程节点无定义
# # 远程节点的工作进程无法导入本地主模块的 add_local 函数,也无法序列化传递普通函数,可能会直接抛出 SerializationError
# # 单进程/单节点下调用指针函数可以执行,但是分布式情况下,local_func 无法被序列化,会出错
return func(x, y) # 报错:NameError,PicklingError 或 SerializationError
# 调用会抛出异常
try:
result = ray.get(execute_func.remote(add, 4, 6))
except Exception as e:
print("错误:", e) # 提示无法序列化或找不到函数
ray.shutdown()核心原因:Ray 远程函数执行依赖序列化传输和集群节点间代码同步
- 未注册的本地函数无法被序列化为集群可识别的任务,且远程节点没有该函数的定义,会导致执行失败
正确示例(远程函数调用)
Ray 的远程函数依赖集群调度,通过
@ray.remote显式注册后使用远程调用函数调用1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31import ray
ray.init(ignore_reinit_error=True)
# 定义远程函数(会注册到 Ray 集群)
def add(a, b):
return a + b
# 远程函数,可接收其他远程函数的调用结果
def execute_func(func, x, y):
# 这里 func 是远程函数标识,通过 .remote() 触发执行
result = ray.get(func.remote(x, y)) # 使用远程调用的方式调用函数指针,实现调用远程函数,正确!
# result = func(x, y) # remote 函数无法被直接调用,错误!
# result = add(x,y) # remote 函数无法被直接调用,错误!
# result = add_local(x, y) # add_local 当做 local 函数调用(注意:不再是指针传入),正确!
return result
# # 不使用 remote 直接调用 远程函数,错误
# result1 = add(2, 3)
# 使用remote直接调用远程函数,正确
result1 = ray.get(add.remote(2, 3))
print("直接调用结果:", result1) # 输出:5
# 间接通过另一个远程函数调用(模拟"传递函数逻辑")
result2 = ray.get(execute_func.remote(add, 2, 3))
print("间接调用结果:", result2) # 输出:10
ray.shutdown()Ray 的远程函数依赖集群调度,需通过
@ray.remote显式注册,无法像本地代码那样传递函数指针(内存地址在分布式环境中无效)若需在远程函数中复用其他函数逻辑,直接传递已注册的远程函数名(如示例中的
add),再通过func.remote()调用即可