如何控制Ray Serve运行时的总内存占用?
Ray Serve Actor内存持续上涨控制方案
根因说明
你配置的object_store_memory仅控制Ray集群共享对象存储的内存上限,你观测到的actor进程自身RSS内存(堆内存、本地临时对象占用)不受该参数限制。同时Ray 1.7及更早版本存在已知的返回大对象时引用泄漏bug,actor返回的numpy数组会被Ray底层残留持有引用,GC无法回收,最终导致内存持续上涨。
解决方法
方案1:升级Ray版本(优先推荐)
Ray 1.8及以上版本修复了Serve场景下的对象引用泄漏问题,同时新增了完整的replica内存管控能力,升级后内存上涨问题会直接缓解。
方案2:无法升级版本时的手动优化
配置单Actor内存硬限制
在ray_actor_options中添加memory参数指定单actor内存上限(单位为字节),超过阈值后Ray会自动重启该actor,避免内存无限制上涨:
@serve.deployment( # 原有配置不变 ray_actor_options={"num_cpus": 1, "memory": 2 * 1024 ** 3}, # 单actor最高占用2GB内存 )
配置副本自动重启
添加max_requests_per_replica参数,指定每个replica处理固定请求数后自动销毁重建,直接清空累计内存:
@serve.deployment( # 原有配置不变 max_requests_per_replica=10000 # 每处理1万请求自动重启 )
优化返回逻辑避免引用泄漏
不要直接返回numpy等大对象,先手动序列化为字节流,切断Ray底层对返回对象的引用持有:
async def __call__(self, request): step_cnt = await request.json() state = np.random.randint(0, 255, (1000, 1000), np.uint8) # 序列化后返回,避免引用泄漏 return state.tobytes()
手动触发GC回收
在请求处理逻辑末尾主动触发GC,清理临时对象:
async def __call__(self, request): # 原有处理逻辑不变 import gc gc.collect() return response
方案3:管控Ray集群总内存
Ray 1.x版本在ray.init时添加_memory参数指定集群总内存配额(单位为字节),所有actor、任务的内存总和不会超过该阈值,超出后Ray会自动终止优先级低的进程,避免整机内存耗尽:
ray.init( num_cpus=1, dashboard_host="0.0.0.0", object_store_memory=8 * 1024 ** 3, # 8GB共享对象存储 _memory=32 * 1024 **3 # 集群总内存上限32GB )
内容的提问来源于stack exchange,提问作者Rong
相关产品推荐
相关产品推荐

