如何通过并行处理调用全部可用CPU核心完成多模型拟合?
问题解答
1. 并行实现是否正确
你的并行实现逻辑是正确的:你将三个独立的模型训练任务封装为Ray远程任务,并行提交后等待返回结果,最终运行耗时确实低于串行,符合并行优化的预期。
不过当前实现存在可优化的冗余开销:你每次给worker传递大数组X、y时,Ray会给每个worker单独拷贝一份数据,三份拷贝的耗时会抵消一部分并行带来的收益。你可以提前把数据存入Ray的共享对象存储,减少拷贝成本:
# 替换原来的传参逻辑 X_id = ray.put(X) y_id = ray.put(y) results = ray.get([worker.remote(model, X_id, y_id) for model in models_to_try])
优化后并行耗时会进一步降低。
2. Ray的CPU调用逻辑和sklearn的差异
- 无参
ray.init()确实会默认识别机器所有可用逻辑核心,作为集群的总CPU配额。但Ray默认不会主动给单个任务分配多核心资源:你没有给@ray.remote装饰器指定num_cpus参数时,每个远程任务默认只占用1个CPU配额,同时Ray会对任务做CPU资源隔离,限制任务最多只能用到1个核心的算力。 - sklearn的
n_jobs=-1是模型训练逻辑内部主动发起多线程/多进程并行,直接占用所有可用核心,没有上层的资源限制,所以能跑满所有核心。
你当前看不到核心跑满的核心原因是:Ray给每个worker任务限制了1核的资源上限,哪怕内部sklearn想调用多核心,也会被隔离规则限制。
3. 核心占用和并行收益的问题
- 你当前的测试场景下,每个worker任务确实只占用1个核心:3个任务总共只用了3核,剩下的5核处于空闲状态,所以没有打满8核的性能。
- 单个任务能不能用到多核心,取决于两点:一是任务本身的代码是否支持多线程/多进程并行,二是你给Ray任务分配的CPU配额。比如你想要随机森林训练用到2核,可以这么写:
@ray.remote(num_cpus=2) def worker(model, X, y): if model == 'random_forest': # 模型内部也设置用2核,和Ray分配的配额匹配 return RandomForestClassifier(random_state=0, n_jobs=2).fit(X=X, y=y) # 其余逻辑不变
- 不是只有任务数大于等于核心数才有并行的意义:如果单个任务本身就能用到多核心,比如一个任务就能占满8核,那1个任务也能跑满所有资源。只有当所有任务都是单线程、每个只占1核的时候,才需要任务数≥核心数才能打满CPU。另外并行的收益还要扣除任务调度、数据拷贝的开销,如果任务本身耗时很短,并行的开销可能比节省的时间还多,这种场景就没必要做并行。
内容的提问来源于stack exchange,提问作者Marthijn
相关产品推荐
相关产品推荐

