使用Python进行并发和并行编程:提高效率的秘诀

使用Python进行并发和并行编程:提高效率的秘诀

​ 大家好,今天我们来聊聊如何使用Python进行并发和并行编程,以提升数据处理的效率;在之前的文章中,我们探讨了Python的函数式编程和数据流处理。今天,我们将进一步讨论如何利用Python中的并发和并行编程来优化我们的程序性能。

文章目录

    • 使用Python进行并发和并行编程:提高效率的秘诀
      • 并发和并行的区别
      • Python中的并发编程
        • 使用`threading`模块
        • 线程安全和共享数据
      • Python中的并行编程
        • 使用`multiprocessing`模块
        • 进程间通信
      • 异步编程
        • 使用`asyncio`模块
        • 异步I/O操作
      • 实际应用场景
        • 案例研究:并发与并行在机器学习中的应用
      • 最佳实践和注意事项
      • 结语

并发和并行的区别

首先,让我们了解一下并发和并行的区别:

  • 并发:指在同一时间段内管理多个任务,任务之间可以交替执行。例如,在单核CPU上可以通过时间片轮转实现并发、
  • 并行:指在同一时刻执行多个任务,通常需要多核CPU支持。例如,在四核CPU上可以同时运行四个任务。

并发和并行虽然听起来类似,但其应用场景和实现方式有所不同。理解这两者的区别有助于我们在不同场景下选择合适的编程方法。

Python中的并发编程

​ Python中的并发编程可以通过threading模块来实现,threading模块提供了一个高层次的接口,允许我们轻松地创建和管理线程,线程是操作系统能够进行独立调度和分配的基本单位。

使用threading模块

​ 以下是一个使用threading模块的简单示例,演示如何创建和启动多个线程来处理并发任务:

import threading
import time

def worker(name):
    print(f'{name} 开始工作')
    time.sleep(2)
    print(f'{name} 工作结束')

threads = []
for i in range(5):
    thread = threading.Thread(target=worker, args=(f'线程 {i+1}',))
    threads.append(thread)
    thread.start()

for thread in threads:
    thread.join()

print('所有线程工作结束')

​ 上面的示例创建了5个线程,每个线程都会执行worker函数,并在函数中休眠2秒钟。在实际应用中,并发编程可以用于处理多个I/O操作,例如同时读取多个文件或处理多个网络请求,从而提高整体处理效率。值得注意的是,Python的全局解释器锁(GIL)限制了多线程在CPU密集型任务中的性能提升,但对于I/O密集型任务,多线程仍然是非常有效的解决方案。

线程安全和共享数据

​ 在多线程编程中,共享数据可能会导致竞争条件(race condition)和数据不一致的问题,为了避免这些问题,可以使用线程锁(lock)来确保同一时间只有一个线程访问共享资源:

import threading

lock = threading.Lock()
counter = 0

def increment_counter():
    global counter
    with lock:
        counter += 1

threads = [threading.Thread(target=increment_counter) for _ in range(100)]
for thread in threads:
    thread.start()
for thread in threads:
    thread.join()

print(f'最终计数值:{counter}')

Python中的并行编程

​ 对于CPU密集型任务,使用multiprocessing模块可以更好地利用多核CPU的优势,multiprocessing模块允许我们创建多个进程,每个进程独立运行在不同的CPU核心上。

使用multiprocessing模块

​ 以下是一个使用multiprocessing模块的示例,演示如何创建和启动多个进程来处理并行任务:

import multiprocessing
import time

def worker(name):
    print(f'{name} 开始工作')
    time.sleep(2)
    print(f'{name} 工作结束')

processes = []
for i in range(5):
    process = multiprocessing.Process(target=worker, args=(f'进程 {i+1}',))
    processes.append(process)
    process.start()

for process in processes:
    process.join()

print('所有进程工作结束')

​ 上面的示例创建了5个进程,每个进程都会执行worker函数,并在函数中休眠2秒钟;并行编程特别适合处理需要大量计算的任务,例如大数据处理、科学计算和图像处理等领域。

进程间通信

​ 在多进程编程中,进程之间的通信(IPC)是一个重要的课题,multiprocessing模块提供了多种IPC机制,如管道(pipe)和队列(queue),使得进程之间能够安全地交换数据:

import multiprocessing

def worker(queue):
    queue.put('消息来自子进程')

if __name__ == '__main__':
    queue = multiprocessing.Queue()
    process = multiprocessing.Process(target=worker, args=(queue,))
    process.start()
    print(queue.get())
    process.join()

异步编程

​ 对于I/O密集型任务,异步编程可以显著提高效率,Python的asyncio模块提供了对异步编程的支持,使我们能够编写高效的异步代码。

使用asyncio模块

​ 以下是一个使用asyncio模块的示例,演示如何使用异步函数处理网络请求:

import asyncio

async def worker(name):
    print(f'{name} 开始工作')
    await asyncio.sleep(2)
    print(f'{name} 工作结束')

async def main():
    tasks = []
    for i in range(5):
        task = asyncio.create_task(worker(f'任务 {i+1}'))
        tasks.append(task)

    await asyncio.gather(*tasks)
    print('所有任务工作结束')

asyncio.run(main())

​ 上面的示例创建了5个异步任务,每个任务都会执行worker函数,并在函数中异步休眠2秒钟;异步编程非常适合处理需要等待的操作,例如网络请求、数据库查询和文件读写等。

异步I/O操作

asyncio模块的强大之处在于能够处理大量并发I/O操作。以下示例展示了如何使用asyncio进行并发HTTP请求:

import asyncio
import aiohttp

async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    async with aiohttp.ClientSession() as session:
        tasks = [fetch(session, f'http://example.com/{i}') for i in range(10)]
        responses = await asyncio.gather(*tasks)
        for response in responses:
            print(response)

asyncio.run(main())

​ 上面的示例使用aiohttp库进行异步HTTP请求,同时处理多个URL,提高了网络请求的效率。

实际应用场景

并发和并行编程在许多实际应用中都非常有用,以下是几个例子:

  • 网页爬虫:可以使用多线程或异步编程来加速网页抓取过程。例如,Scrapy就是一个基于异步编程的高效爬虫框架。
  • 数据分析:可以使用多进程并行处理大数据集,提高数据分析的速度。例如,Pandas可以与multiprocessing结合使用,实现并行数据处理。
  • 机器学习:可以使用多进程并行训练多个模型或并行处理大规模数据。例如,scikit-learn支持并行训练多个模型,提高训练速度。
案例研究:并发与并行在机器学习中的应用

​ 在机器学习项目中,模型训练通常是一个计算密集型任务。使用多进程并行处理可以显著减少训练时间,以下示例展示了如何使用joblib库实现并行模型训练:

from joblib import Parallel, delayed
from sklearn.datasets import make_classification
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score

def train_model(seed):
    X, y = make_classification(n_samples=1000, n_features=20, random_state=seed)
    model = RandomForestClassifier(random_state=seed)
    scores = cross_val_score(model, X, y, cv=5)
    return scores.mean()

seeds = range(10)
results = Parallel(n_jobs=-1)(delayed(train_model)(seed) for seed in seeds)
print(results)

​ 示例使用joblib库的Paralleldelayed函数来并行化模型训练,提高了训练速度。

最佳实践和注意事项

在使用并发和并行编程时,以下是一些最佳实践和注意事项:

  • 避免共享状态:尽量避免在线程或进程之间共享状态,以减少竞争条件和数据不一致的问题。可以使用线程安全的队列(例如queue.Queue)或进程安全的队列(例如multiprocessing.Queue)来进行数据交换。
  • 使用线程池和进程池:使用concurrent.futures模块中的ThreadPoolExecutorProcessPoolExecutor来管理线程和进程池,提高代码的可维护性和效率。例如:
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor

def worker(name):
    print(f'{name} 开始工作')
    time.sleep(2)
    print(f'{name} 工作结束')

# 使用线程池
with ThreadPoolExecutor(max_workers=5) as executor:
    for i in range(5):
        executor.submit(worker, f'线程 {i+1}')

# 使用进程池
with ProcessPoolExecutor(max_workers=5) as executor:
    for i in range5:
        executor.submit(worker, f'进程 {i+1}')

  • 异常处理:在并发和并行编程中,添加适当的异常处理机制,以应对潜在的错误和异常。例如,可以在任务函数中添加try-except块,并记录异常日志。
  • 优化性能:在处理大规模数据时,注意优化性能,避免不必要的计算和资源浪费。例如,可以使用NumPy等高效的数值计算库,提高数据处理效率。

结语

​ 通过学习并应用Python中的并发和并行编程技术,我们可以显著提升程序的效率和性能。希望大家在实际项目中多多尝试使用这些技术,提升代码的运行效率。如果你有任何问题或想法,欢迎在评论区留言。Happy coding!
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SGPT论文阅读笔记

这是篇想要用GPT来提取sentence embedding的工作,提出了两个框架,一个是SGPT-BE,一个是SGPT-CE,分别代表了Bi-Encoder setting和Cross-Encoder setting。CE的意思是在做阅读理解任务时,document和query是一起送进去&am…

【启明智显产品介绍】Model4 工业级HMI芯片详解系列专题(二):高清解码

Model4 工业级HMI芯片详解系列专题(二)【高清解码】 Model4 工业级HMI芯片集成了图形显示和编解码相关的硬件模块,为高清图像显示、高清视频播放和高清摄像头输入提供了强大的硬件基础: DE 显示引擎: 1 个 UI 图层&…

Unity引擎UGUI上特效处理重叠和裁剪问题的多种解决办法

大家好,我是阿赵。   使用Unity引擎开发项目,使用UGUI做界面,经常会遇到需要把特效放在UI上,但UI本身和特效又需要有遮挡关系和裁剪效果。   之前我介绍了一下使用MaskableGraphic的方式把粒子特效渲染在UI上,把粒…

电手出软件啦!各种姿势一键重装你的系统

电手的兄弟们你们好啊,很多兄弟都知道,我们老大傲梅是做软件的,例如大伙儿都用过的傲梅分区助手,还有傲梅轻松备份。相信不少兄弟都是用了分区助手才关注到电手的。 而我们电手,在电脑和手机玩机内容方面一直深耕。 跟…

【车载音视频AI电脑】全国产海事船载视频监控系统解决方案

海事船载视频监控系统解决方案针对我国快速发展的内河航运、沿海航运和远洋航运中存在的航行安全和航运监管难题,为船舶运营方、政府监管部门提供一套集视频采集、存储、回放调阅为一体的视频监控系统,对中大型船舶运行中的内部重要部位情况和外部环境进…

实现锚点链接点击tab跳转到指定位置 并且滚动鼠标顶部锚点的样式也跟随变化

实现效果如下 不管是点击还是 滚动鼠标 顶部的样式也会跟随变化 点击会跳转到指定的位置 通过IntersectionObserver 监听是否可见 下面代码可以直接执行到vue的文件 <template><div><ul class"nav"><li v-for"tab in tabs" :key…

京东和天猫各渠道区别是什么?你了解吗?如何快速了解两个平台渠道推广

1.快车/直通车区别: 京东:不能投竞品词,能投定向商品选竞品,因为京东是卖平台流量和商品(自营(主收入)),不可以投竞品词是为了保护自己店铺的品牌流量; 天猫:只卖平台流量,不卖商品,所以允许竞品词投放; 2.竞品人群圈选: 因为数坊是自身品牌数据分析平台,所…

php配合fiddler批量下载淘宝天猫商品数据分享

有个做电商的朋友问我&#xff0c;每次上款&#xff0c;需要手动去某宝去搬运商品图片视频&#xff0c;问我能不能帮忙写个脚本&#xff0c;朋友开口了&#xff0c;那就尝试一下 首先打开某宝&#xff0c;访问一款商品&#xff0c;找出他的数据来源 通过观察我们发现主图数据来…

C# 与三菱PLC MC协议通讯

1. 引用HslCommunication Nuget包里边添加 HslCommunication包的引用 2.创建PLC连接对象&#xff0c;并通过 IP&#xff0c;端口进行连接 //PLC连接对象 var plc new MelsecMcNet(_ip, _port); plc.ConnectTimeOut 3000;var res plc.ConnectServer();//连接PLCisConnect …

苹果Mac电脑遭恶意软件攻击 Mac第三方恶意软件删除不了

苹果Mac电脑一直以来都以安全性和稳定性著称&#xff0c;许多用户认为Mac电脑不会受到恶意软件的侵害&#xff0c;但事实上&#xff0c;Mac电脑也不是绝对安全的&#xff0c;近年来&#xff0c;有越来越多的恶意软件针对Mac电脑进行攻击&#xff0c;甚至有些恶意软件可以绕过苹…

镭速是如何做到传输中快速校验大文件的

在信息泛滥的当下&#xff0c;文件传输系统的效率与安全性成为企业和个人用户高度关注的焦点。传统上&#xff0c;文件传输依赖于如MD5或XXHash等单一的完整性校验机制。 然而&#xff0c;在多变的工作环境中&#xff0c;这些传统方法显得不够灵活。镭速&#xff0c;作为大文件…

文库小程序搭建部署:实现资源共享正向反馈

文档库相信大家应该不陌生&#xff0c;日常我们的工作模板、会议模板、求职时的简历模板、教育界的教学模板等来源方式都出自于文档库&#xff0c;随着互联网的发展和工作需求&#xff0c;文档模板开启了新型的知识变现新途径&#xff0c;通过文库小程序&#xff0c;我们不仅能…

9.2.2 DeepLab系列模型中每一代的创新是什么?是为了解决什么问题?

9.2.2 DeepLab系列模型中每一代的创新是什么&#xff1f;是为了解决什么问题&#xff1f; 前情回顾&#xff1a;9.2.1 简述图像分割中经常用到的编码器-解码器网络结构的设计理念。 DeepLab是Google 团队提出的一系列图像分割算法。 DeepLab v1在2014年被提出&#xff0c;并在…

ROS std_msgs消息包

ROS std_msgs消息包 基本概述 std_msgs 是 ROS&#xff08;Robot Operating System&#xff09;的一个核心消息包&#xff0c;包含了一系列基本的消息类型&#xff0c;这些类型用于节点之间的标准通信。std_msgs 中的消息类型设计得非常简单&#xff0c;以便用作更复杂消息的…

升级你的App推广策略!Xinstall用户来源朔源功能引领行业新潮流

一、引言 在App推广和运营的道路上&#xff0c;你是否曾经遇到过这样的困境&#xff1a;投入了大量的资源&#xff0c;但用户增长却迟迟不见起色&#xff1f;或是用户增长迅速&#xff0c;但用户留存率却极低&#xff1f;这些问题&#xff0c;往往源于我们对用户来源的不了解。…

vue echarts画多柱状图+多折线图

<!--多柱状图折线图--> <div class"echarts-box" id"multiBarPlusLine"></div>import * as echarts from echarts;mounted() {this.getMultiBarPlusLine() },getMultiBarPlusLine() {const container document.getElementById(multiBar…

Windows11电脑在使用GPU的时候有时候会卡顿

原来我一直以为是电脑的某些组件可能坏掉了 但是后来发现通过更新gpu的驱动可以让它变好&#xff1a; NVIDIA GeForce 驱动程序 - N 卡驱动 | NVIDIA 下载好以后&#xff0c;然后安装最新的驱动就可以了&#xff0c;感觉可能是因为win11和某些需要显卡的驱动不支持的原因吧 …

分布式技术导论 — 探索分析从起源到现今的巅峰之旅(消息队列)

探索分析从起源到现今的巅峰之旅 分布式队列 - Kafka架构特性可扩展性磁盘优化与顺序访问大容量存储与历史数据利用高效数据封装与压缩智能内存管理与OS缓存利用 Kafka发布/订阅模型Kafka架构分析Producer和Consumer接口交互Producer通过Topic发送数据Consumer通过Topic消费数据…

Java 解析xml文件-工具类

Java 解析xml文件-工具类 简述 Java解析xml文件&#xff0c;对应的Javabean是根据xml中的节点来创建&#xff0c;如SeexmlZbomord、SeexmlIdoc等等 工具类代码 import cn.hutool.core.io.FileUtil; import com.alibaba.cloud.commons.io.IOUtils; import com.seexml.bom.Se…

充电宝什么牌子好?买多少毫安充电宝合适?这几个误区别踩!

在选择充电宝时&#xff0c;很多消费者常常被各种品牌和容量规格搞得眼花缭乱。不少人认为&#xff0c;容量越大越好&#xff0c;但事实并非如此。其实&#xff0c;根据日常使用需求&#xff0c;选择10000毫安的充电宝已经足够应对大多数情况。10000毫安的充电宝不仅能够满足手…