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

news2024/10/6 4:04:16

多进程实现CPU并行计算

  • 1、引言
  • 2、实战
    • 2.1 多进程模式
      • 2.1.1 定义
      • 2.1.2 multiprocessing
      • 2.1.3 模式
      • 2.1.4 适用场景
      • 2.1.4 代码示例
    • 2.2 执行方法
      • 2.2.1 多线程并发执行
      • 2.2.2 进程池
      • 2.2.3 消息队列
      • 2.2.4 内存共享
      • 2.2.5 异步IO
  • 3、总结

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技术。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/704689.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

神奇的甲方:恰恰是拔高我们最好的机遇!

✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…

LeetCode 打卡day52--动态规划之子序列问题

一个人的朝圣 — LeetCode打卡第52天 知识总结 Leetcode 300. 最长递增子序列题目说明代码说明 Leetcode 674. 最长连续递增序列题目说明代码说明 Leetcode 718. 最长重复子数组题目说明代码说明 知识总结 今天运用动态规划来解决子序列问题. 子序列 是由数组派生而来的序列&a…

Debezium系列之:深入理解tinyint(n)

Debezium系列之:深入理解tinyint 一、背景二、相关技术博客三、查看表的ddl四、深入理解tinyint(n)五、创建表六、插入数据七、查看topic数据八、总结一、背景 数据库修改了字段类型为tinyint,希望采集的时候能够转化为boolean类型,数据库字段类型如下图所示: 在设置了conv…

机器学习笔记 - Facebook AI Similarity Search(Faiss)简介

一、概述 Facebook AI Similarity Search (Faiss)是高效相似性搜索最受欢迎的轮子之一。给定一组向量,我们可以使用 Faiss 对它们进行索引——然后使用另一个向量(查询向量),我们在索引中搜索最相似的向量。 它包含搜索任何大小的向量集的算法,除非超出RAM的大小。它还包…

Go 语言精进之路——Go语言代码块与作用域理解

文章目录 前言代码块与作用域简介if 条件控制语句的代码块其他控制语句的代码块 前言 如果不深入理解 Go 语言的代码块作用域,程序将产生我们无法理解的行为,比如说在循环中创建 goroutine func, 为什么需要传递参数至 goroutine 内部,否则所…

柠檬精僵尸2023-2024_wb粉丝清道夫比赛博更好用的方法

微博批量移除微博粉丝方法_可视化的界面 多样性选择你要移除清理的粉丝类型 三个按钮就可以搞定了 移除粉丝步骤: 首先打开微博,登陆自己的账号。 找到你想要删除的粉丝,点开他/她的头像,打开他/她的个人主页 如果想要大批量清理…

尚硅谷Docker实战教程-笔记04【Docker镜像】

尚硅谷大数据技术-教程-学习路线-笔记汇总表【课程资料下载】视频地址:尚硅谷Docker实战教程(docker教程天花板)_哔哩哔哩_bilibili 尚硅谷Docker实战教程-笔记01【理念简介、官网介绍、平台入门图解、平台架构图解】尚硅谷Docker实战教程-笔…

accountId、uid、roleId 游戏中的3种id

1)accountId: // 是一个字符串 这个是字符串,玩家可以输入名字(比如:输入zfoo) 或者 通过微信生成(openid是不变的)。 2)uid:// long 这个是一个很长的,玩家通过http登录授权后,通过web层,由雪花算法根据accountId生成…

【每天40分钟,我们一起用50天刷完 (剑指Offer)】第十一天 11/50

专注 效率 记忆 预习 笔记 复习 做题 欢迎观看我的博客,如有问题交流,欢迎评论区留言,一定尽快回复!(大家可以去看我的专栏,是所有文章的目录)   文章字体风格: 红色文字表示&#…

Selenium上传文件有多少种方式?不信你有我全

Selenium 封装了现成的文件上传操作。但是随着现代前端框架的发展,文件上传的方式越来越多样。而有一些文件上传的控件,要做自动化控制会更复杂一些,这篇文章主要讨论在复杂情况下,如何通过自动化完成文件上传 1.input 元素上传文…

【FFmpeg实战】AAC编码, 解码

使用命令行进行AAC编码 // PCM的三要素采样率,声道数, 采样格式 ffmpeg -ar 44100 -ac 2 -f s16le -i in.pcm out.aac// -c:a codec:audio 指定的是音频编码 ffmpeg -ar 44100 -ac 2 -f s16le -i in.pcm -c:a libfdk_aac out.aacffmpeg -ar 44100 -ac …

哪些辅助工具支持快递单号的批量查询

当我们批量发出大量快递时,有什么查询软件可以快速查询和跟踪批量每个单号的物流信息,及时跟踪物流状态?今天,我来安利一个软件:“固乔快递查询助手”,可以实现这个功能。我们一起来看看软件的使用和操作步…

C++类与对象(默认成员函数之拷贝构造函数)

接前几次的类与对象的默认函数的知识点,下来面是默认成员函数中的拷贝构造函数。是的,它的名字是拷贝构造函数,他其实也是一种构造函数,为什么呢?接下来你就知道了,我们直接看看代码,如下&#…

【AICG】【Midjourney】AI自动生成图片的初接触

背景 现在是AI 比较流行,公司也推荐学习和了解AI的相关东西。 公司的内部培训中涉及到了Midjourney的简单讲解。 效果 由于我的账号注册的时候过了free窗口期: 现在要我花钱订阅: 只能看看其他人的帖子过过AI生成的瘾。 如图所示&#x…

【TA100】4.2 SSAO算法 屏幕空间环境光遮蔽

1 SSAO介绍 1.1 环境光遮蔽(AO) 全称Ambient Occlusion,是计算机图形学中一种着色和渲染技术,模拟光线达到物体的能力的粗略的全局方法,描述光线到达物体表面的能力。 这个场景看起来没有表示颜色的贴图,但是场景的…

SC5103接口可pin对pin兼容TLK1501

SC5103 用于超高速双向点对点数据传输系统。SC5103 支持 0.6Gbps 至 1.5Gbps 的有效串行接口速度,提供高达 1.2Gbps 的有效数据带宽。可pin对pin兼容TLK1501。 SC5103 可替代并行传输数据结构从而减少传输路径数、连接端子数、发送/接收端子数。并行数据被发送链路转…

求职贴 | 多源融合定位方向24届硕士秋招求职

求职方向 多源融合定位 / LIO / VIO 基本情况 现就读于华中区某985,研究方向为多源融合定位,主要内容是LiDAR / IMU融合两篇期刊论文在投,论文内容即项目经历;具有丰富的电子设计类竞赛经历自我认为学习能力强,爱动…

JavaSE-15 【异常】

文章目录 JavaSE-15 【异常】第一章 什么是异常1.1 异常的概念1.2 异常的体系1.3 异常的分类1.4 异常产生的过程 第二章 异常的处理2.1 抛出异常throw2.2 声明异常throws2.3 捕获异常try...catch2.4 finally 代码块2.5 异常注意事项 第三章 自定义异常3.1 自定义异常概述3.2 自…

工业物联网解决方案:远程组态监控管理系统

如何高效的采集和集中工业设备PLC运行数据、工艺参数、产品质量等生产数据,通过数据分析反馈在制造工艺、生产流程、质量管理、设备维护和能耗管理的智能应用,这是工业远程组态监控管理系统可以解决的问题,也是众多工厂企业关注的重点。 工…