怎么编写Python代码让数据处理快4倍
这篇文章主要介绍"怎么编写Python代码让数据处理快4倍",在日常操作中,相信很多人在怎么编写Python代码让数据处理快4倍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"怎么编写Python代码让数据处理快4倍"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
普通Python处理数据方法
比方说:
我们有一个全是图像数据的文件夹,想用Python为每张图像创建缩略图。
下面是一个短暂的脚本:
用Python的内置glob函数获取文件夹中所有JPEG图像的列表,
然后用Pillow图像处理库为每张图像保存大小为128像素的缩略图:
这段脚本沿用了一个简单的模式
你会在数据处理脚本中经常见到这种方法:
首先获得你想处理的文件(或其它数据)的列表
写一个辅助函数,能够处理上述文件的单个数据
使用for循环调用辅助函数,处理每一个单个数据,一次一个。
咱们用一个包含1000张JPEG图像的文件夹测试一下这段脚本,
看看运行完要花多长时间:
运行程序花了8.9秒,但是电脑的真实工作强度怎样呢?
我们再运行一遍程序
看看程序运行时的活动监视器情况:
电脑有75%的处理资源处于闲置状态!这是什么情况?
这个问题的原因就是我的电脑有4个CPU,但Python只使用了一个。
所以程序只是卯足了劲用其中一个CPU,另外3个却无所事事。
因此我需要一种方法能将工作量分成4个我能并行处理的单独部分。
幸运的是,Python中有个方法很容易能让我们做到!
试试创建多进程
下面是一种可以让我们并行处理数据的方法:
将JPEG文件划分为4小块。运行Python解释器的4个单独实例。
让每个Python实例处理这4块数据中的一块。
将这4部分的处理结果合并,获得结果的最终列表。
4个Python拷贝程序在4个单独的CPU上运行,
处理的工作量应该能比一个CPU大约高出4倍,
对吧?
最妙的是,Python已经替我们做完了最麻烦的那部分工作。
我们只需告诉它想运行哪个函数以及使用多少实例就行了,剩下的工作它会完成。
整个过程我们只需要改动3行代码。
首先
我们需要导入concurrent.futures库
这个库就内置在Python中:
接着,我们需要告诉Python启动4个额外的Python实例。
我们通过让Python创建一个Process Pool来完成这一步:
默认情况下:
它会为你电脑上的每个CPU创建一个Python进程,
所以如果你有4个CPU,就会启动4个Python进程。
***一步:
让创建的Process Pool用这4个进程在数据列表上执行我们的辅助函数。
完成这一步,我们要将已有的for循环:
替换为新的调用executor.map():
该executor.map()函数调用时需要输入辅助函数和待处理的数据列表。
这个函数能帮我完成所有麻烦的工作
包括将列表分为多个子列表、将子列表发送到每个子进程、运行子进程以及合并结果等。
干得漂亮!
这也能为我们返回每个函数调用的结果。
Executor.map()函数会按照和输入数据相同的顺序返回结果。
所以我用了Python的zip()函数作为捷径,一步获取原始文件名和每一步中的匹配结果。
这里是经过这三步改动后的程序代码:
我们来运行一下这段脚本
看看它是否以更快的速度完成数据处理:
脚本在2.2秒就处理完了数据!比原来的版本提速4倍!
之所以能更快的处理数据
是因为我们使用了4个CPU而不是1个。
但是
如果你仔细看看,会发现"用户"时间几乎为9秒。
那为何程序处理时间为2.2秒,但不知怎么搞得运行时间还是9秒?
这似乎不太可能啊?
这是
因为"用户"时间是所有CPU时间的总和,
我们最终完成工作的CPU时间总和一样,都是9秒,
但我们使用4个CPU完成的,实际处理数据时间只有2.2秒!
注意:
启用更多Python进程以及给子进程分配数据都会占用时间,因此靠这个方法并不能保证总是能大幅提高速度。
这种方法总能帮我的数据处理脚本提速吗?
如果你有一列数据
并且每个数据都能单独处理时,使用我们这里所说的Process Pools是一个提速的好方法。
下面是一些适合使用并行处理的例子:
从一系列单独的网页服务器日志里抓取统计数据。
从一堆XML,CSV和JSON文件中解析数据。
对大量图片数据做预处理,建立机器学习数据集。
但也要记住,Process Pools并不是***的。
使用Process Pool需要在独立的Python处理进程之间来回传递数据。
如果你要处理的数据不能在处理过程中被有效地传递,这种方法就行不通了。
简而言之,你处理的数据必须是Python知道怎么应对的类型。
同时
也无法按照一个预想的顺序处理数据。
如果你需要前一步的处理结果来进行下一步,这种方法也行不通。
那GIL的问题呢?
你可能知道Python有个叫全局解释器锁(Global Interpreter Lock)的东西,即GIL。
这意味着即使你的程序是多线程的,每个线程也只能执行一个Python指令。
GIL确保任何时候都只有一个Python线程执行。
换句话说:
多线程的Python代码并不能真正地并行运行,从而无法充分利用多核CPU。
但是Process Pool能解决这个问题!
因为我们是运行单独的Python实例,每个实例都有自己的GIL。
这样我们获得是真正能并行处理的Python代码!
到此,关于"怎么编写Python代码让数据处理快4倍"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!