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

多进程vs迭代实现性能疑问:为何迭代方式更快?

问题分析与解决方案

你的判断完全正确——进程创建/销毁的开销远超过了多进程并行带来的收益,因为单个count_bugs_needed任务的计算量不足以抵消进程启动、IPC(进程间通信)的成本,最终导致多进程版本反而更慢。

具体原因拆解

  • 进程本身的开销:创建子进程需要操作系统复制父进程的内存空间(即使有写时复制优化,仍有初始化、调度、销毁的固定开销),这些开销对于轻量级计算任务来说占比极高。
  • 任务特性:count_bugs_needed里的循环虽然有41600次迭代,但每次只是简单的随机数生成和整数运算,属于超轻量计算,单线程就能在极短时间内完成,进程开销完全盖过了多核并行的收益。
  • 代码额外放大开销:当前多进程逻辑中,每次批量创建24个进程后都要销毁重建,还反复创建新的Queue,进一步增加了不必要的系统调用开销;同时用Queue.get()阻塞等待结果的方式,也会带来额外的通信延迟。

改进方案

1. 用进程池复用进程

使用multiprocessing.Pool代替手动创建Process,进程池会预先创建一批进程并复用,彻底避免反复创建销毁进程的开销。

2. 分摊进程开销

让每个子进程处理多次任务(而非单次),将进程启动的固定开销分摊到更多计算上,提升并行效率。

3. 简化IPC逻辑

进程池的map/imap方法比手动维护Queue更高效,减少进程间通信的复杂度和延迟。

修改后的代码示例

import collections
import math
import random

from time import perf_counter
from multiprocessing import Pool

import matplotlib.pyplot as plt

MULTIPROCESSING = True

MAX_PROCESSES = 24
TRIALS = 10000

def count_bugs_needed(_):
    fragments = 0
    bugs_killed = 0
    drop_chance = .77

    while fragments < 41600:
        bugs_killed += 1
        if random.randint(1,100) >= int((1-drop_chance) * 100):
            fragments += 1
    return bugs_killed
        
if __name__ == '__main__':
    start_time = perf_counter()
    bug_count = []        

    if not MULTIPROCESSING:
        for x in range(TRIALS):    
            bug_count.append(count_bugs_needed(1))
            if (x+1) % MAX_PROCESSES == 0:
                speed = (x+1) / (perf_counter() - start_time)
                print(f"Iterations done: {x+1}, Speed: {speed:.2f} ITERATIONS PER SECOND")
    else:
        # 进程池复用进程,避免反复创建销毁的开销
        with Pool(processes=MAX_PROCESSES) as pool:
            # 流式获取结果,无需等待全部任务完成
            for idx, result in enumerate(pool.imap_unordered(count_bugs_needed, range(TRIALS)), 1):
                bug_count.append(result)
                if idx % MAX_PROCESSES == 0:
                    speed = idx / (perf_counter() - start_time)
                    print(f"Iterations done: {idx}, Speed: {speed:.2f} ITERATIONS PER SECOND")

    print("Done generating values. Starting to graph.")
    
    bug_count_sorted = sorted(bug_count)
    counter = collections.Counter(bug_count_sorted)
    sorted_counter = sorted(counter.items())
    unique_bug_counts = [item[0] for item in sorted_counter]
    frequencies = [item[1] for item in sorted_counter]

    plt.scatter(unique_bug_counts, frequencies)
    max_freq = max(frequencies)
    plt.ylim(0, int(max_freq * 1.2 + 1))
    plt.yticks(range(0, int(max_freq * 1.2 + 1) + 1))
    plt.title('Frequency of bug kills for 41600 fragments')
    plt.xlabel('Bugs killed')
    plt.ylabel('Frequency')
    plt.show()

改进效果预期

修改后,多进程版本的速度会显著超过单线程迭代版本:进程池的复用消除了大部分进程开销,多核CPU的并行计算能力得以发挥,同时流式获取结果的方式也避免了不必要的等待。

内容的提问来源于stack exchange,提问作者Dont worry about it

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 15:39:55