Python 多线程、多进程、协程对迭代数据的耗时操作测试

2023-10-29

Python 多线程、多进程、协程对迭代数据的耗时操作测试

2023-03-29

CPU计算密集型:

2.17s/p

Python中的多线程受GIL制约,因此表面上的并行,实际上是并发,完全的计算密集型任务就和串行的耗时差不多了;

Deal 耗时 备注
普通的循环执行 22.68 串行
线程池执行 22.10 并发
进程池执行 6.95 并行
协程执行(多线程) 22.39 并发
协程执行(多进程) 6.67 并行
协程执行(多进程,更直接的方式,无嵌套调用) 6.88 并行
协程执行(多进程,并测试异步迭代器的使用) 7.52 并行

I/O密集型:

1s/p

I/O密集型的任务,表面是并行,实际也可以当做并行看待,基本不受GIL的影响,甚至由于开销少,耗时会更短;

Deal 耗时 备注
普通的循环执行 25.05 串行
线程池执行 5.01 并行
进程池执行 6.12 并行
协程执行(多线程) 5.01 并行
协程执行(多进程) 5.04 并行
协程执行(多进程,更直接的方式,无嵌套调用) 5.04 并行
协程执行(多进程,并测试异步迭代器的使用) 5.03 并行

测试代码

  • 引入头文件:
# pip install aiohttp
import nest_asyncio

nest_asyncio.apply()  # PyCharm中 不需要这两句

import time
import asyncio
import concurrent.futures
from multiprocessing import Pool

  • 线程/进程池的数量设为5:

POOL_SIZE = 5


def download_file(row):
    # 非协程对象支持(耗时操作模拟)
    #     print(row,'_downloading')
    # I/O密集模拟
    time.sleep(1)
    # 计算密集模拟
    #     total = 0
    #     for i in range(10000000):
    #         total += i
    #         total -= i

    #     print(row,'_downloaded')
    return row


async def download_prepare(row, pool):
    # 协程对象支持(基于线程/进程池包装非协程对象,返回Future对象)
    # 在协程对象中 可以await另一个协程对象 如果要支持非协程对象的方法调用 就需要结合线程/进程池
    loop = asyncio.get_event_loop()
    fut = loop.run_in_executor(pool, download_file, row)
    response = await fut


class Reader(object):
    def __init__(self, datalist, pool=None):
        self.datalist = iter(datalist)
        self.pool = pool

    async def readrow(self):
        try:
            row = next(iter(self.datalist))
            # 创建task 需要传入一个协程对象(对应要执行的方法)
            task = asyncio.create_task(download_prepare(row, self.pool))
            # 返回一个可等待对象(这里是Task)
            return task
        except StopIteration:
            return None

    def __aiter__(self):
        return self

    async def __anext__(self):
        val = await self.readrow()
        if val == None:
            raise StopAsyncIteration
        return val


# 普通的循环执行
def main(datalist):
    for row in datalist:
        download_file(row)


# 线程池执行
def main1(datalist):
    threadpool = concurrent.futures.ThreadPoolExecutor(POOL_SIZE)
    for row in datalist:
        # 注意在等待时,与主线程无关,主线程依然在继续执行。
        threadpool.submit(download_file, row)
    threadpool.shutdown(True)  # 等待线程池中的任务执行完毕后,在继续执行


# 进程池执行
def main2(datalist):
    pool = Pool(POOL_SIZE)
    pool.map(download_file, datalist)
    pool.close()  # 关闭进程池,不再接受新的进程
    pool.join()  # 主进程阻塞等待子进程的退出


#  协程执行(多线程)
def main3(datalist):
    with concurrent.futures.ThreadPoolExecutor(max_workers=POOL_SIZE) as pool:
        tasks = [asyncio.create_task(download_prepare(row, pool)) for row in datalist]

        loop = asyncio.get_event_loop()
        loop.run_until_complete(asyncio.wait(tasks))


#  协程执行(多进程)
def main4(datalist):
    with concurrent.futures.ProcessPoolExecutor(max_workers=POOL_SIZE) as pool:
        tasks = [asyncio.create_task(download_prepare(row, pool)) for row in datalist]

        loop = asyncio.get_event_loop()
        loop.run_until_complete(asyncio.wait(tasks))


#  协程执行(多进程,更直接的方式,无嵌套调用)
def main5(datalist):
    loop = asyncio.get_running_loop()
    with concurrent.futures.ProcessPoolExecutor(max_workers=POOL_SIZE) as pool:
        futs = []
        for row in datalist:
            futs.append(loop.run_in_executor(pool, download_file, row))

        done_s, pending_s = asyncio.run(asyncio.wait(futs))

#         print(done_s, pending_s)


#  协程执行(多进程,并测试异步迭代器的使用)
async def main6(datalist):
    with concurrent.futures.ProcessPoolExecutor(max_workers=POOL_SIZE) as pool:
        obj_t = Reader(datalist, pool)
        tasks = []
        async for task in obj_t:
            tasks.append(task)

        done_s, pending_s = await asyncio.wait(tasks)


#         print(done_s, pending_s)

  • 迭代25个数据,分别测试计算密集型、I/O密集型任务在不同场景下的耗时:

if __name__ == "__main__":

    print(time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()))
    t1 = time.time()
    datalist = [
        "0_0_0_0_353",
        "1_1_0_0_353",
        "2_2_0_0_353",
        "3_4_0_0_353",
        "4_5_0_0_353",
        "0_0_0_0_353",
        "1_1_0_0_353",
        "2_2_0_0_353",
        "3_4_0_0_353",
        "4_5_0_0_353",
        "0_0_0_0_353",
        "1_1_0_0_353",
        "2_2_0_0_353",
        "3_4_0_0_353",
        "4_5_0_0_353",
        "0_0_0_0_353",
        "1_1_0_0_353",
        "2_2_0_0_353",
        "3_4_0_0_353",
        "4_5_0_0_353",
        "0_0_0_0_353",
        "1_1_0_0_353",
        "2_2_0_0_353",
        "3_4_0_0_353",
        "4_5_0_0_353",
    ]

    main(datalist)  # 10s
    print("串行:普通的循环执行——执行时间:", float(time.time() - t1), "秒")
    t1 = time.time()
    main1(datalist)  # 6s
    print("并发:线程池执行——执行时间:", float(time.time() - t1), "秒")
    t1 = time.time()
    main2(datalist)  # 6s
    print("并行:进程池执行——执行时间:", float(time.time() - t1), "秒")
    t1 = time.time()
    main3(datalist)  # 6s
    print("并发:协程执行(多线程)——执行时间:", float(time.time() - t1), "秒")
    t1 = time.time()
    main4(datalist)  # 6s
    print("并行:协程执行(多进程)——执行时间:", float(time.time() - t1), "秒")
    t1 = time.time()
    main5(datalist)  # 6s
    print("并行:协程执行(多进程,更直接的方式,无嵌套调用) ——执行时间:", float(time.time() - t1), "秒")
    t1 = time.time()
    asyncio.run(main6(datalist))  # 6s
    print("并行:协程执行(多进程,并测试异步迭代器的使用)  ——执行时间:", float(time.time() - t1), "秒")
    print(time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()))
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python 多线程、多进程、协程对迭代数据的耗时操作测试 的相关文章

随机推荐

  • python作品-python实例作品

    广告关闭 腾讯云双11爆品提前享 精选热门产品助力上云 云服务器首年88元起 买的越多返的越多 最高满返5000元 多尺度模板匹配结果不要拿我的话来说 这种方法的作品 我们来看一些例子 打开您的终端并执行以下命令 multi scale t
  • unity3d coroutine、invoke的应用

    提供了两种异步方式的调用 1 coroutine 协程 应该是untity对c 多线程的一种封装吧 内部不是很了解 调用的函数需标示IEnumerator迭代配合yield return xxx使用 yield标示着是否暂停迭代 yield
  • 荣耀Magicbook安装黑苹果教程(OpenCore引导)

    荣耀笔记本电脑Magicbook安装黑苹果双系统教程 有空再写 可以先看下面的参考资料 准备工作 系统 macOS 12 3 1 Monterey 21E258 u盘 两个 一个用于安装黑苹果系统 一个用于引导修复 磁盘分区等工作 无线网卡
  • Java 正确的做字符串编码转换

    Java 正确的做字符串编码转换 字符串的内部表示 字符串在java中统一用unicode表示 即utf 16 LE 对于 String s 你好哦 如果源码文件是GBK编码 操作系统 windows 默认的环境编码为GBK 那么编译时 J
  • 2013年度总结 -- 向着IT前进

    各位朋友 请将手机调整到飞行模式 我们将乘时光机回到2013年元月 一起见证作者Mr Chen在过去这一年里的 丰功伟绩 现在开始闭上眼睛 进入倒计时10 9 8 7 6 5 4 3 2 1 2013年元月 上线前的冲刺 兄弟们 辛苦一下
  • 【工具使用】STM32CubeMX-DMA配置(ADC+DMA 和 UART+DMA)

    一 概述 无论是新手还是大佬 基于STM32单片机的开发 使用STM32CubeMX都是可以极大提升开发效率的 并且其界面化的开发 也大大降低了新手对STM32单片机的开发门槛 本文主要讲述STM32芯片的DMA的配置及其相关知识 二 软件
  • 计算机快捷键大全截图,电脑截图快捷键是哪个?电脑快捷键使用大全

    原标题 电脑截图快捷键是哪个 电脑快捷键使用大全 在电脑日常工作中 截图是经常会使用到的功能 相信绝大数的用户都是通过第三方截图软件 比如QQ 旺旺等程序自带的电脑截图功能 却不知道Win系统中也是自带截图工具 和键盘上某键配合使用 键盘上
  • Vue 路由的params参数

    1 路由的params参数 1 配置路由 声明接收params参数 routes path about component About component Home children path news component News com
  • android flash无图标,Android - Android - 安装应用(APP) 不显示桌面图标、隐藏图标

    PackageManager COMPONENT ENABLED STATE ENABLED 显示应用图标 PackageManager COMPONENT ENABLED STATE DISABLED 隐藏应用图标 我用这俩个值来显示和隐
  • 天龙3d服务器维护,《新天龙八部》2017年3月6日全服更新维护公告

    亲爱的玩家 大家好 为保证游戏运行的稳定性 提升整体服务质量 新天龙八部 游戏全部服务器 部分服务器将提前至5 00维护 具体服务器列表请见公告下方 将于2017年3月6日7 00 9 00进行更新维护 维护后版本号升级为3 61 5303
  • -bash: /usr/bin/yum: No such file or directory解决方案

    删除了yum文件 导致yum命令出现 bash情况 root localhost yum bash usr bin yum No such file or directory 解决方案 http mirrors 163 com centos
  • el-select下拉框:数据回显后,无法重新选中或修改

    选中其他值以后 数据并没有发生改变 且无法选中 解决 给el select 点击事件 change getTeacherId 强制数据刷新 表单同理 input getTeacherId getTeacherId val this next
  • 数据可视化第四章

    比例数据 是根据类别 子类别和群体来进行划分的数据 对于比例 通常想要得到最大值 最小值和总体分布 前两者比较简单 将数据由小到大进行排列 位于两端的分别就是最小值和最大值 数据对比也是比例可视化的一个重要应用 在一个图表中集中反映多个维度
  • 小程序页面滚动穿透

    小程序页面滚动穿透 一 场景 框架 Taro2 Taro3不生效的 在项目当中 基础遇到这样的需求 有一个长列表 或者其他可滚动展示的页面 在这个页面会弹出一个Modal层 如下 贝壳找房的 的筛选栏 二 问题 如果这个弹框内容不可滚动 不
  • java 获取系统 默认编码_Java获取Linux服务器系统默认编码格式

    一 查找java进程 ps ef grep java 二 使用jinfo命令查看java系统参数 jinfo sysprops 进程id Usage jinfo option to connect to running process ji
  • 建立良好人际关系的原则

    1 尊重原则 尊重包括两个方面 自尊和尊重他人 自尊就是在各种场合都要尊重自己 维护自己的尊严 不要自暴自弃 尊重他人就是要尊重别人的生活习惯 兴趣爱好 人格和价值 只有尊重别人才能得到别人的尊重 2 真诚原则 只有诚以待人 胸无城府 才能
  • 【图论——第四讲】dijkstra算法求单源最短路及其堆优化

    o 大家好 欢迎大家光临我的博客 面向阿尼亚学习 算法学习笔记系列持续更新中 文章目录 一 前言 二 朴素dijkstra算法 三 堆优化版dijkstra 最后 一 前言 单源最短路 指的是求一个点 到其他所有点的最短距离 即起点是固定的
  • linux系统中函数库,Linux函数库(静态函数库和动态函数库)及安装过程

    Linux 系统中存在大量的函数库 简单来讲 函数库就是一些函数的集合 每个函数都具有独立的功能且能被外界调用 我们在编写代码时 有些功能根本不需要自己实现 直接调用函数库中的函数即可 需要注意的是 函数库中的函数并不是以源代码的形式存在的
  • 从0到1设计通用数据大屏搭建平台

    优质资源分享 学习路线指引 点击解锁 知识定位 人群定位 Python实战微信订餐小程序 进阶级 本课程是python flask 微信小程序的完美结合 从项目搭建到腾讯云部署上线 打造一个全栈订餐系统 Python量化交易实战 入门级 手
  • Python 多线程、多进程、协程对迭代数据的耗时操作测试

    Python 多线程 多进程 协程对迭代数据的耗时操作测试 2023 03 29 CPU计算密集型 2 17s p Python中的多线程受GIL制约 因此表面上的并行 实际上是并发 完全的计算密集型任务就和串行的耗时差不多了 Deal 耗