Ray中ObjectRef被自动收集并反序列化的异常原因咨询
Ray中ObjectRef被自动收集并反序列化的异常原因咨询
看起来你遇到的问题核心是不小心调用了两次buffer.add.remote,导致add方法被执行了两次,其中第二次的参数已经是反序列化后的numpy数组,而非ObjectRef,从而触发了ray.get的报错。我们来一步步拆解原因:
问题根源分析
先看你的循环代码:
while sp_refs: complete, sp_refs = ray.wait(sp_refs) print(f"{complete=}") buffer.add.remote(complete) # 这里是多余的调用! for r in complete: buffer_refs.append(buffer.add.remote(r))
你在这里做了重复操作:
- 第一行
buffer.add.remote(complete):把整个已完成的ObjectRef列表传给了add方法 - 随后循环
complete里的每个r,调用buffer.add.remote(r):把单个ObjectRef传给add方法
这直接导致add方法被执行两次,对应两种不同的参数情况:
- 第一次调用:参数是ObjectRef列表
- 你在
add里调用ray.get(experience),会批量获取列表中所有ObjectRef的值,得到numpy数组的列表,这和你输出里的第一次打印结果完全吻合。
- 你在
- 第二次调用:参数本应是单个ObjectRef,但实际变成了numpy数组
- 当你第一次调用
ray.get(complete)时,已经获取了这些ObjectRef对应的numpy数组。结合Ray Actor的执行逻辑,第二次传递同一个ObjectRef时,会自动传递已解析的值而非引用(虽然Ray的ObjectRef设计上支持重复使用,但你的代码执行顺序触发了自动解包)。 - 此时
add方法接收的是已经反序列化的numpy数组,再调用ray.get(experience)自然会报错——因为ray.get只接受ObjectRef或ObjectRef列表,不接受numpy数组。
- 当你第一次调用
解决方案
只需要去掉那行多余的buffer.add.remote(complete)即可,修改后的循环代码:
while sp_refs: complete, sp_refs = ray.wait(sp_refs) print(f"{complete=}") # 移除多余的批量调用 for r in complete: buffer_refs.append(buffer.add.remote(r))
这样add方法只会被调用一次,每次接收单个ObjectRef,调用ray.get(experience)就能正确获取到numpy数组了。
另外,建议你调整add方法的参数类型标注,如果以后可能需要处理列表,可以改成Union[ray.ObjectRef, List[ray.ObjectRef]],避免类型混淆带来的问题。
备注:内容来源于stack exchange,提问作者Vaas




