关于python加速的一些心得(一)

在python中,我们可以通过concurrent.futures 的 ProcessPoolExecutor 创建多进程,实现并行方式,从而提高运算速度

举个例子,我们写了个一个函数fibonacci, 用于计算斐波那契数

# 计算斐波那契数的函数
def fibonacci(n):
    if n <= 1:
        return n
    else:
        return fibonacci(n-1) + fibonacci(n-2)

如果我们是顺序运算,那么用时10.5秒,平均每个任务2秒。

%%time

# 顺序计算斐波那契数
def compute_fibonacci(numbers):
    for num in numbers:
        result = fibonacci(num)
        print(f'Fibonacci({num}) = {result}')

# 要计算的斐波那契数列表
numbers = [35, 35, 35, 35, 35]

compute_fibonacci(numbers)

# 时间
CPU times: user 10.5 s, sys: 0 ns, total: 10.5 s
Wall time: 10.5 s

如果是并行运算,那么用时只需要2.36 s,比原来快了将近4倍。

%%time

from concurrent.futures import ProcessPoolExecutor, as_completed

# 使用 ProcessPoolExecutor 计算斐波那契数
def compute_fibonacci(numbers):
    # 创建 ProcessPoolExecutor
    with ProcessPoolExecutor() as executor:
        # 提交任务到进程池
        futures = [executor.submit(fibonacci, num) for num in numbers]
        
        # 等待每个任务完成并获取结果
        for future in as_completed(futures):
            result = future.result()
            print(f'Result: {result}')

# 要计算的斐波那契数列表
numbers = [35, 35, 35, 35, 35]

compute_fibonacci(numbers)

# 时间
CPU times: user 16.6 ms, sys: 140 ms, total: 157 ms
Wall time: 2.36 s

需要注意的是,我们案例用的是numbers = [35, 35, 35, 35, 35], 假设,我们换成 numbers = [1] * 100, 那么顺序执行只需要485 µs,而并行却需要2.35 s,反而速度更慢了。

根据上述案例,就可以得到关于python加速的一个心得,无脑多进程不可取,因为多进程存在额外开销,例如

  1. 进程创建和管理:ProcessPoolExecutor 使用多进程并行处理任务,进程的创建和管理(启动、通信、结束)本身就有一定的开销。对于非常快速的计算任务(如计算斐波那契数1),这种开销可能远远超过了任务本身的计算时间。
  2. 任务分配和结果收集:在并行执行时,每个任务都需要从主进程发送到工作进程,然后工作进程完成计算后,结果还需要发送回主进程。这个过程涉及到序列化和反序列化数据,以及进程间通信的开销,这些都会影响总体执行时间。

因此,在使用concurrent模块时,需要先用少量数据测试下是否真的值得并行。

# 并行 

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×