Python中的并行编程速度
这里主要想记录下今天碰到的一个小知识点:Python中的并行编程速率如何?
我想把AutoTool做一个并行化改造,主要目的当然是想提高多任务的执行速度。第一反应就是想到用多线程执行不同模块任务,但是在我收集Python多线程编程资料的时候发现一个非常奇怪的信息,那就是Python的多线程并不是真正的多线程,因为有一个GIL的存在(可以参考这篇文章讲解《Python最难的问题》)导致Python实际上默认(CPython解释器)只能是单线程执行。
这里我写了一个例子可以看看:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File : batch_swig_runner.py
# @Time : 2019/7/8 18:09
# @Author : KuLiuheng
# @Email : liuheng.klh@alibaba-inc.com from swig_runner import SwigRunner import time
import logging
from threading import Thread
from multiprocessing import Pool class TestRunner(Thread):
def __init__(self, name, path):
super(TestRunner, self).__init__()
self.name = name
self.path = path def run(self):
logging.warning("Message from the thread-%s START" % self.name)
for i in range(10000000): # 耗时操作模拟
j = int(i) * 10.1
# time.sleep(1)
logging.warning("Message from the thread-%s END" % self.name)
return self.path def multi_process(mname, mpath):
logging.warning("Message from the thread-%s START" % mname)
for i in range(10000000): # 耗时操作模拟
j = int(i) * 10.1
# time.sleep(1)
logging.warning("Message from the thread-%s END" % mname) class BatchSwigRunner(object):
def __init__(self, modules=None):
"""
用模块信息字典(工程名: 工程路径)来初始化
:param modules: {工程名: 工程路径}
"""
if modules is not None:
self._modules = modules
else:
self._modules = dict() def add_module_info(self, name, path):
self._modules[name] = path def start(self):
"""
启动批量任务执行,并返回执行过程中的错误信息
:return: list(工程序号,工程名称) 出错的工程信息列表
"""
runners = list()
for (project_name, project_path) in self._modules.items():
# logging.warning('BatchSwigRunner.start() [%s][%s]' % (project_name, project_path))
sub_runner = TestRunner(project_name, project_path)
sub_runner.daemon = True
sub_runner.start()
runners.append(sub_runner) for runner in runners:
runner.join() if __name__ == '__main__':
batch_runner = BatchSwigRunner()
batch_runner.add_module_info('name1', 'path1')
batch_runner.add_module_info('name2', 'path2')
batch_runner.add_module_info('name3', 'path3')
batch_runner.add_module_info('name4', 'path4')
start_time = time.time()
batch_runner.start() print 'Total time comsumed = %.2fs' % (time.time() - start_time) print('========================================')
start_time = time.time() for index in range(4):
logging.warning("Message from the times-%d START" % index)
for i in range(10000000): # 耗时操作模拟
j = int(i) * 10.1
# time.sleep(1)
logging.warning("Message from the times-%d END" % index) print '>>Total time comsumed = %.2fs' % (time.time() - start_time) print('----------------------------------------------')
start_time = time.time() pool = Pool(processes=4)
for i in range(4):
pool.apply_async(multi_process, ('name++%d' % i, 'path++%d' % i))
pool.close()
pool.join()
print '>>>> Total time comsumed = %.2fs' % (time.time() - start_time)
看结果就发现很神奇的结论:
C:\Python27\python.exe E:/VirtualShare/gitLab/GBL-310/GBL/AutoJNI/autoTool/common/batch_swig_runner.py
WARNING:root:Message from the thread-name4 START
WARNING:root:Message from the thread-name2 START
WARNING:root:Message from the thread-name3 START
WARNING:root:Message from the thread-name1 START
WARNING:root:Message from the thread-name2 END
WARNING:root:Message from the thread-name4 END
WARNING:root:Message from the thread-name3 END
Total time comsumed = 15.92s
========================================
WARNING:root:Message from the thread-name1 END
WARNING:root:Message from the times-0 START
WARNING:root:Message from the times-0 END
WARNING:root:Message from the times-1 START
WARNING:root:Message from the times-1 END
WARNING:root:Message from the times-2 START
WARNING:root:Message from the times-2 END
WARNING:root:Message from the times-3 START
WARNING:root:Message from the times-3 END
>>Total time comsumed = 11.59s
----------------------------------------------
WARNING:root:Message from the thread-name++0 START
WARNING:root:Message from the thread-name++1 START
WARNING:root:Message from the thread-name++2 START
WARNING:root:Message from the thread-name++3 START
WARNING:root:Message from the thread-name++1 END
WARNING:root:Message from the thread-name++0 END
WARNING:root:Message from the thread-name++2 END
WARNING:root:Message from the thread-name++3 END
>>>> Total time comsumed = 5.69s Process finished with exit code 0
其运行速度是(计算密集型):multiprocessing > normal > threading.Thread
请注意这里用的是持续计算来模拟耗时操作:
for i in range(10000000): # 耗时操作模拟
j = int(i) * 10.1
如果用空等待(time.sleep(1)类似IO等待)来模拟耗时操作,那么结果就是(IO等待型):threading.Thread > multiprocessing > normal
C:\Python27\python.exe E:/VirtualShare/gitLab/GBL-310/GBL/AutoJNI/autoTool/common/batch_swig_runner.py
WARNING:root:Message from the thread-name4 START
WARNING:root:Message from the thread-name2 START
WARNING:root:Message from the thread-name3 START
WARNING:root:Message from the thread-name1 START
WARNING:root:Message from the thread-name3 END
WARNING:root:Message from the thread-name4 END
WARNING:root:Message from the thread-name2 END
WARNING:root:Message from the thread-name1 END
WARNING:root:Message from the times-0 START
Total time comsumed = 1.01s
========================================
WARNING:root:Message from the times-0 END
WARNING:root:Message from the times-1 START
WARNING:root:Message from the times-1 END
WARNING:root:Message from the times-2 START
WARNING:root:Message from the times-2 END
WARNING:root:Message from the times-3 START
WARNING:root:Message from the times-3 END
>>Total time comsumed = 4.00s
----------------------------------------------
WARNING:root:Message from the thread-name++0 START
WARNING:root:Message from the thread-name++1 START
WARNING:root:Message from the thread-name++2 START
WARNING:root:Message from the thread-name++3 START
WARNING:root:Message from the thread-name++0 END
WARNING:root:Message from the thread-name++1 END
WARNING:root:Message from the thread-name++2 END
WARNING:root:Message from the thread-name++3 END
>>>> Total time comsumed = 1.73s Process finished with exit code 0
为何会有这样的结果呢?
(1)threading机制中因为GIL的存在,实际上是一把全局锁让多线程变成了CPU线性执行,只可能用到一颗CPU计算。当sleep这样是释放CPU操作发生时,可以迅速切换线程,切换速度可以接受(比multiprocessing快),比normal(阻塞等待)当然快的多;
(2)这里用了多进程Pool,可以真正意义上使用多CPU,对于CPU计算密集型的操作(上面的for循环计算)那么肯定是多核比单核快。所以就出现了第一种测试场景的结果。
Python中的并行编程速度的更多相关文章
- .Net中的并行编程-4.实现高性能异步队列
上文<.Net中的并行编程-3.ConcurrentQueue实现与分析>分析了ConcurrentQueue的实现,本章就基于ConcurrentQueue实现一个高性能的异步队列,该队 ...
- Python中的并发编程
简介 我们将一个正在运行的程序称为进程.每个进程都有它自己的系统状态,包含内存状态.打开文件列表.追踪指令执行情况的程序指针以及一个保存局部变量的调用栈.通常情况下,一个进程依照一个单序列控制流顺序执 ...
- .Net中的并行编程-2.ConcurrentStack的实现与分析
在上篇文章<.net中的并行编程-1.基础知识>中列出了在.net进行多核或并行编程中需要的基础知识,今天就来分析在基础知识树中一个比较简单常用的并发数据结构--.net类库中无锁栈的实现 ...
- .Net中的并行编程-3.ConcurrentQueue实现与分析
在上文<.Net中的并行编程-2.ConcurrentQueue的实现与分析> 中解释了无锁的相关概念,无独有偶BCL提供的ConcurrentQueue也是基于原子操作实现, 由于Con ...
- .Net中的并行编程-6.常用优化策略
本文是.Net中的并行编程第六篇,今天就介绍一些我在实际项目中的一些常用优化策略. 一.避免线程之间共享数据 避免线程之间共享数据主要是因为锁的问题,无论什么粒度的锁 ...
- .Net中的并行编程-5.流水线模型实战
自己在Excel整理了很多想写的话题,但苦于最近比较忙(其实这是借口).... 上篇文章<.Net中的并行编程-4.实现高性能异步队列>介绍了异步队列的实现,本篇文章介绍我实际工作者遇到了 ...
- Python 中的 TK编程
可爱的 Python:Python 中的 TK编程 http://www.ibm.com/developerworks/cn/linux/sdk/python/charm-12/ python che ...
- 可爱的 Python : Python中的函数式编程,第三部分
英文原文:Charming Python: Functional programming in Python, Part 3,翻译:开源中国 摘要: 作者David Mertz在其文章<可爱的 ...
- .Net中的并行编程-1.路线图(转)
大神,大神,膜拜膜拜,原文地址:http://www.cnblogs.com/zw369/p/3834559.html 目录 .Net中的并行编程-1.路线图 分析.Net里线程同步机制 .Net中的 ...
随机推荐
- java上传1t文件
我们平时经常做的是上传文件,上传文件夹与上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用.此控件PC全平台支持包括mac,linux系统的文件上传,文章末尾将附上控件下载与教程链接 ...
- hihoCoder 1785
线性筛 + 递推 #include <bits/stdc++.h> , Mod = 1e9 + ; int n; int phi[N], prime[N], tot, ans; bool ...
- 分治 FFT学习笔记
先给一道luogu板子题:P4721 [模板]分治 FFT 今天模拟有道题的部分分做法是分治fft,于是就学了一下.感觉不是很难,国赛上如果推出式子的话应该能写出来. 分治fft用来解决这么一个式子\ ...
- RESTFUL API 安全认证方式
一般基于REST API 安全设计常用方式有: HTTP Basic Basic admin:admin Basic YWRtaW46YWRtaW4= Authorization: Basic YWR ...
- XFTP 乱码
- javascript 闭包(closure)
<script type="text/javascript"> //闭包(closure):内层函数可以引用存在于包围它的函数内的变量,即使外层函数的执行已经结束 ...
- TopCoder SRM 582 Div 1 - Problem 1000 SemiPerfectPower
首先我们可以把答案差分,那么我们只需要求出\(1\)~\(x\)范围内的满足条件的数即可. 题目要求的应该是这个东西的个数: \(l \leq a*b^c \leq r(1 \le a < b) ...
- [转载]virtual topology虚拟拓扑
原文地址:topology虚拟拓扑">virtual topology虚拟拓扑作者:一丝尘埃 topology虚拟拓扑" title="[转载]virtual to ...
- 运维管理SLA
主要三个概念: SLI 服务关键量化指标,即测试哪些指标,如何测等 SLO :服务等级目标,即要达到哪些目标,如设备正常率3个9.4个9等,即99.9% SLA: 服务等级协议,即如果未完成SLO中 ...
- django + vue3 解决跨越问题
django跨域 解决: https://yq.aliyun.com/articles/517215 vue3 跨越(此处没必要,django处理即可): https://blog.csdn.net/ ...