Python3,如何实现CPU的并行计算,那还不简单,5种方式,这篇就搞定。

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: Python3,如何实现CPU的并行计算,那还不简单,5种方式,这篇就搞定。

1、引言

小屌丝:鱼哥,你上一篇《Python3,掌握这几种并行处理,轻轻松松提升for循环速度》写的很赞, 我还想继续深入并行计算

小鱼:那你的意思,哪一篇写的不深呗?

小屌丝:我可没有那个意思。

小鱼:我也没说你是哪个意思。

小屌丝:我就是想着你能不能再讲一讲,关于如何实现CPU并行计算。

小鱼:我屮艸芔茻…你这是有啥心思?

小屌丝:我… 我没有。

小鱼:如实说来,或许,我还能讲一讲。

小屌丝:当真?

小鱼:当真…

小屌丝:就是,我要在公司分享一些技术,就涉及到 如何实现CPU并行计算方面的姿势 . 知识。

小鱼:这样啊, 那你直接说就好了。 我又不是特别喜欢黑桃A。

小屌丝:… 整,整,整吧。

2、实战

2.1 多进程模式

这里,我们主要以Python中的额多进程模式进行讲解。

2.1.1 定义

  • 在Python中,多进程模式是指同时运行多个进程来执行任务的一种编程模式。
  • Python提供了多个模块来支持多进程编程,其中最常用的是multiprocessing模块。

2.1.2 multiprocessing

  • 使用multiprocessing模块可以创建和管理多个进程,每个进程都有自己独立的内存空间和执行环境。
  • 通过将任务分配给不同的进程,可以实现并行执行,提高程序的运行效率。

2.1.3 模式

  • 在多进程模式下,每个进程都有自己的主程序流程,可以独立执行任务。
  • 进程之间可以通过进程间通信(IPC)机制来进行数据交换和同步操作。

2.1.4 适用场景

  • 多进程模式适用于需要充分利用多核处理器或执行耗时任务的场景。
  • 通过将任务分配给多个进程,可以充分利用系统资源,提高程序的运行效率。

2.1.4 代码示例

代码示例

# -*- coding:utf-8 -*-
# @Time   : 2023-07-01
# @Author : Carl_DJ
import multiprocessing
def worker(num):
    """子进程的任务函数"""
    print(f'Worker {num} started')
    # 执行一些任务
    print(f'Worker {num} finished')
if __name__ == '__main__':
    # 创建多个子进程
    processes = []
    for i in range(5):
        p = multiprocessing.Process(target=worker, args=(i,))
        processes.append(p)
        p.start()
    # 等待所有子进程结束
    for p in processes:
        p.join()
    print('All workers finished')

2.2 执行方法

2.2.1 多线程并发执行

多进程模式下,将任务分配给多个进程并行执行,从而利用多核CPU的优势。

这可以说作为一名码农,必备的知识点。

这里,我们同样使用multiprocessing 来实现一个并发执行任务的示例。

代码示例

# -*- coding:utf-8 -*-
# @Time   : 2023-07-01
# @Author : Carl_DJ
import multiprocessing
def task(name):
    print(f"Running task {name}")
if __name__ == "__main__":
    # 创建进程池,最大进程数为4
    pool = multiprocessing.Pool(processes=4)
    # 提交任务到进程池
    for i in range(10):
        pool.apply_async(task, args=(i,))
    # 关闭进程池,不再接受新的任务
    pool.close()
    # 等待所有任务完成
    pool.join()
    print("All tasks completed")

解析:

  • 首先创建了一个进程池,最大进程数为4;
  • 其次使用apply_async方法提交了10个任务到进程池中;
  • 最后,我们关闭进程池并等待所有任务完成。

2.2.2 进程池

对于大量重复的任务,

使用进程池来维护一定数量的进程,每个进程执行一个任务后返回结果,然后再由进程池分配下一个任务。

这样的好处就是:避免频繁地创建和销毁进程,从而提高效率。

我们使用 multiprocessing模块的Pool类来实现进程池。

代码示例

# -*- coding:utf-8 -*-
# @Time   : 2023-07-01
# @Author : Carl_DJ
import multiprocessing
def worker(num):
    print('Worker', num)
if __name__ == '__main__':
    # 创建一个进程池,最大进程数为3
    pool = multiprocessing.Pool(processes=3)
    # 使用进程池执行任务
    for i in range(5):
        pool.apply_async(worker, (i,))
    # 关闭进程池,不再接受新的任务
    pool.close()
    # 等待所有任务完成
    pool.join()

解析:

  • 首先,创建了一个进程池,最大进程数为3;
  • 其次,使用进程池的apply_async方法提交任务,每个任务都会由进程池中的一个空闲进程执行;
  • 最后,关闭进程池并等待所有任务完成。

2.2.3 消息队列

在多进程模式下,不同的进程之间需要进行通信,可以利用消息队列来实现进程间通信。

我们使用Queue模块来实现消息队列。

代码示例

# -*- coding:utf-8 -*-
# @Time   : 2023-07-01
# @Author : Carl_DJ
from queue import Queue
import time
# 创建一个消息队列
message_queue = Queue()
# 生产者函数,向消息队列中添加消息
def producer():
    for i in range(5):
        message = f"Message {i+1}"
        message_queue.put(message)
        print(f"Produced: {message}")
        time.sleep(1)
# 消费者函数,从消息队列中获取消息并处理
def consumer():
    while True:
        message = message_queue.get()
        print(f"Consumed: {message}")
        time.sleep(2)
        message_queue.task_done()
# 创建并启动生产者和消费者线程
producer_thread = threading.Thread(target=producer)
consumer_thread = threading.Thread(target=consumer)
producer_thread.start()
consumer_thread.start()
# 等待生产者和消费者线程结束
producer_thread.join()
consumer_thread.join()

解析:

  • 使用Queue模块创建了一个消息队列message_queue;
  • 生产者函数producer负责向消息队列中添加消息;
  • 消费者函数consumer负责从消息队列中获取消息并进行处理。

2.2.4 内存共享

对于需要多个进程共享的数据,可以使用共享内存来避免数据拷贝和进程间通信的开销。

我们使用multiprocessing模块的Value和Array类来实现共享内存

代码示例

# -*- coding:utf-8 -*-
# @Time   : 2023-07-01
# @Author : Carl_DJ
from multiprocessing import Process, Value, Array
# 定义一个共享变量
shared_value = Value('i', 0)
# 定义一个共享数组
shared_array = Array('d', [0.0, 1.0, 2.0, 3.0, 4.0])
# 定义一个函数,用于修改共享变量和数组的值
def modify_shared_data(value, array):
    value.value = 10
    for i in range(len(array)):
        array[i] = i * 2
# 创建一个子进程,传入共享变量和数组
p = Process(target=modify_shared_data, args=(shared_value, shared_array))
p.start()
p.join()
# 打印共享变量和数组的值
print("Shared value:", shared_value.value)
print("Shared array:", shared_array[:])

解析:

  • 首先,使用Value和Array类分别创建了一个共享变量shared_value和一个共享数组shared_array;
  • 其次,定义了一个函数modify_shared_data,该函数会修改共享变量和数组的值;
  • 第三,创建了一个子进程,将共享变量和数组作为参数传递给子进程;
  • 最后,子进程执行完毕后,输出共享变量和数组的值。

2.2.5 异步IO

对于I/O密集型任务,可以使用异步IO来提高效率。

我们使用asyncio模块来实现异步IO。

代码示例

# -*- coding:utf-8 -*-
# @Time   : 2023-07-01
# @Author : Carl_DJ
import asyncio
async def fetch_data(url):
    print(f"正在请求URL:{url}")
    await asyncio.sleep(2)  # 模拟网络请求延迟
    print(f"请求URL:{url}完成")
    return f"从{url}获取的数据"
async def main():
    urls = [
        "https://www.example.com",
        "https://www.google.com",
        "https://www.baidu.com"
    ]
    tasks = [fetch_data(url) for url in urls]
    results = await asyncio.gather(*tasks)
    print(results)
if __name__ == "__main__":
    asyncio.run(main())

解析:

  • 首先,定义一个fetch_data函数,模拟了一个网络请求,并使用asyncio.sleep来模拟请求的延迟;
  • 其次,在main函数中,创建了多个fetch_data的协程任务,并使用asyncio.gather来并发执行这些任务;
  • 最后,使用asyncio.run来运行main函数。

3、总结

看到这里,今天的分享差不多就到这里了。

今天主要针对在Python中, 使用多进程模式来实现CPU的并行计算。如:

  • 多线程并发执行
  • 进程池
  • 消息队列
  • 内存共享
  • 异步IO

在实际的项目中,很多地方都会用到并行计算, 这不仅提高的代码执行效率, 也提高了用户的满意度。

我是小鱼

  • CSDN 博客专家;
  • 阿里云 专家博主;
  • 51CTO博客专家;
  • 51认证讲师等;
  • 认证金牌面试官;
  • 职场面试及培训规划师;
  • 多个国内主流技术社区的认证专家博主;
  • 多款主流产品(阿里云等)测评一、二等奖获得者;

关注我,带你学习更多更专业更前言的Python技术。

目录
相关文章
|
2月前
|
并行计算 数据处理 Python
Python并发编程迷雾:IO密集型为何偏爱异步?CPU密集型又该如何应对?
在Python的并发编程世界中,没有万能的解决方案,只有最适合特定场景的方法。希望本文能够为你拨开迷雾,找到那条通往高效并发编程的光明大道。
47 2
|
3月前
|
开发框架 并行计算 算法
揭秘Python并发神器:IO密集型与CPU密集型任务的异步革命,你竟还傻傻分不清?
揭秘Python并发神器:IO密集型与CPU密集型任务的异步革命,你竟还傻傻分不清?
50 4
|
2月前
|
监控 并行计算 数据处理
构建高效Python应用:并发与异步编程的实战秘籍,IO与CPU密集型任务一网打尽!
在Python编程的征途中,面对日益增长的性能需求,如何构建高效的应用成为了每位开发者必须面对的课题。并发与异步编程作为提升程序性能的两大法宝,在处理IO密集型与CPU密集型任务时展现出了巨大的潜力。今天,我们将深入探讨这些技术的最佳实践,助你打造高效Python应用。
43 0
|
2月前
|
开发框架 并行计算 .NET
脑洞大开!Python并发与异步编程的哲学思考:IO密集型与CPU密集型任务的智慧选择!
脑洞大开!Python并发与异步编程的哲学思考:IO密集型与CPU密集型任务的智慧选择!
33 1
|
3月前
|
开发框架 并行计算 .NET
燃烧吧,Python!异步编程如何点燃IO密集型任务,让CPU密集型任务也加速狂奔?
燃烧吧,Python!异步编程如何点燃IO密集型任务,让CPU密集型任务也加速狂奔?
26 2
|
3月前
|
算法 Java 程序员
解锁Python高效之道:并发与异步在IO与CPU密集型任务中的精准打击策略!
在数据驱动时代,高效处理大规模数据和高并发请求至关重要。Python凭借其优雅的语法和强大的库支持,成为开发者首选。本文将介绍Python中的并发与异步编程,涵盖并发与异步的基本概念、IO密集型任务的并发策略、CPU密集型任务的并发策略以及异步IO的应用。通过具体示例,展示如何使用`concurrent.futures`、`asyncio`和`multiprocessing`等库提升程序性能,帮助开发者构建高效、可扩展的应用程序。
140 0
|
3月前
|
UED 开发者 Python
Python并发编程新纪元:异步编程如何重塑IO与CPU密集型任务的处理方式?
在Python编程中,异步编程作为一种非阻塞模式,通过允许程序在等待IO操作时继续执行其他任务,提高了程序的响应性和吞吐量。与传统同步编程相比,它减少了线程等待时间,尤其在处理IO密集型任务时表现出色,如使用`asyncio`库进行异步HTTP请求。尽管对CPU密集型任务的直接提升有限,但结合多进程或多线程可间接提高效率。异步编程虽强大,但也带来了代码复杂度增加和调试难度提升等挑战,需要开发者掌握最佳实践来克服这些问题。随着其技术的成熟,异步编程正在逐步改变我们处理IO与CPU密集型任务的方式,成为提升性能和优化用户体验的重要工具。
27 0
|
5月前
|
并行计算 监控 数据处理
构建高效Python应用:并发与异步编程的实战秘籍,IO与CPU密集型任务一网打尽!
【7月更文挑战第16天】Python并发异步提升性能:使用`asyncio`处理IO密集型任务,如网络请求,借助事件循环实现非阻塞;`multiprocessing`模块用于CPU密集型任务,绕过GIL进行并行计算。通过任务类型识别、任务分割、避免共享状态、利用现代库和性能调优,实现高效编程。示例代码展示异步HTTP请求和多进程数据处理。
63 8
|
5月前
|
并行计算 数据处理 Python
Python并发编程迷雾:IO密集型为何偏爱异步?CPU密集型又该如何应对?
【7月更文挑战第17天】Python并发编程中,异步编程(如`asyncio`)在IO密集型任务中提高效率,利用等待时间执行其他任务。但对CPU密集型任务,由于GIL限制,多线程效率不高,此时应选用`multiprocessing`进行多进程并行计算以突破限制。选择合适的并发策略是关键:异步适合IO,多进程适合CPU。理解这些能帮助构建高效并发程序。
127 6
|
5月前
|
算法 Java 程序员
解锁Python高效之道:并发与异步在IO与CPU密集型任务中的精准打击策略!
【7月更文挑战第17天】在数据驱动时代,Python凭借其优雅语法和强大库支持成为并发处理大规模数据的首选。并发与异步编程是关键,包括多线程、多进程和异步IO。对于IO密集型任务,如网络请求,可使用`concurrent.futures`和`asyncio`;CPU密集型任务则推荐多进程,如`multiprocessing`;`asyncio`适用于混合任务,实现等待IO时执行CPU任务。通过这些工具,开发者能有效优化资源,提升系统性能。
102 4