You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Multiprocessing未充分利用CPU问题求助

蒙特卡洛法计算圆周率的CPU利用率优化方案

问题根源

你当前代码的核心问题是在每次N_test循环中重复创建和销毁进程池:进程的启动、初始化及销毁会产生显著的额外开销。当N较小时,任务本身的执行时间远小于进程池的创建销毁时间,导致大部分CPU时间浪费在进程管理上,利用率自然上不去。而增大N后,任务执行时间变长,进程管理开销的占比被稀释,利用率才有所提升,但这并非根本解决办法。

优化步骤及代码实现

1. 核心优化:复用进程池

将进程池的创建移到循环外部,只初始化一次,避免重复的进程创建销毁开销。

2. 任务粒度优化

合并N_test循环的总任务量,一次性拆分给进程池处理,减少主循环的调度开销。

3. 随机数生成优化

替换random模块为numpy的向量化随机数生成——random模块在多进程下存在全局锁竞争,numpy的实现无锁且效率更高。

优化后的代码:

import numpy as np
import multiprocessing
from multiprocessing import Pool

def sample(n):
    # 用numpy向量化生成随机数,替代循环调用random模块
    x = np.random.uniform(0, 1, n)
    y = np.random.uniform(0, 1, n)
    return np.sum(x**2 + y**2 < 1.0)

if __name__ == "__main__":
    N_test = 1000
    N = 12 * 10**4
    n_cpu = multiprocessing.cpu_count()  # 自动获取CPU核心数,代码更通用
    total_samples = N * N_test

    # 只初始化一次进程池,复用所有进程
    with Pool(processes=n_cpu) as pool:
        # 拆分总任务量到各个进程
        per_process = total_samples // n_cpu
        part_counts = [per_process] * n_cpu
        # 处理余数,避免总样本数遗漏
        remainder = total_samples % n_cpu
        if remainder > 0:
            for i in range(remainder):
                part_counts[i] += 1
        
        # 并行执行所有任务
        results = pool.map(sample, part_counts)
        total_inside = sum(results)
        pi = total_inside / total_samples * 4

    print(pi)

额外性能建议

  • 若追求极致效率,可使用pool.imap_unordered替代pool.map——它会在进程完成任务后立即返回结果,减少整体等待时间(求和场景不依赖结果顺序)。
  • 避免在子进程中频繁创建大对象,保持任务逻辑简洁,进一步降低进程间的资源竞争。

内容的提问来源于stack exchange,提问作者Prometeus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 03:51:35