使用Python的ray模块时如何修改共享内存数据避免冗余拷贝?
Ray 只读数组问题的原因和优化方案
你遇到的ValueError: output array is read-only属于Ray的预期行为,既不是使用错误,也不是Ray不适合你的需求。
Ray 将任务传入的不可变对象存储在共享内存中,默认设为只读,核心是为了避免多进程并发修改共享数据产生竞态条件,同时让多个Worker可以直接访问同一份数据,无需重复拷贝,这一设计在大规模多任务并行场景下会大幅降低内存占用和数据传输开销。
当前写法的开销评估
你示例中的np.copy操作属于必要开销:因为你需要返回修改后的新数组,就算Ray允许你修改传入的原数组,你也不能直接修改共享内存中的对象——否则所有依赖该数组的其他任务都会拿到被篡改的数据,反而会产生逻辑错误。
如果你只是想优化拷贝+赋值的两步操作,可以合并成单步写法,性能完全一致:
import numpy as np import ray @ray.remote def mod_arr(arr): return arr + np.ones(arr.shape) ray.init() arr = np.zeros((2,3,4)) arr = ray.get(mod_arr.remote(arr))
降低拷贝开销的可行方案
如果拷贝开销已经成为你的性能瓶颈,可以根据业务逻辑选择对应优化方案:
- 如果该数组只会被单个任务使用,不需要共享给其他任务,可以将数组放在Ray Actor的本地内存中处理,Actor本地的数组默认可写,不需要额外拷贝:
@ray.remote class ArrayProcessor: def __init__(self, arr): self.arr = arr def mod_arr(self): self.arr += np.ones(self.arr.shape) return self.arr ray.init() processor = ArrayProcessor.remote(np.zeros((2,3,4))) arr = ray.get(processor.mod_arr.remote())
- 如果是多任务需要修改同一个大数组的不同分片,可以将数组拆分为多个独立分片,每个分片只分配给一个任务处理,避免跨任务共享,自然不需要额外拷贝。
- 如果你确实需要可变的共享对象,可以使用新版Ray提供的
MutableObjectAPI,显式创建可写的共享内存对象,不过需要自行处理并发修改的锁逻辑,避免数据损坏。
内容的提问来源于stack exchange,提问作者Alf
相关产品推荐
相关产品推荐

