本文对应脚本已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes

一、简介

  进程是计算机系统中资源分配的最小单位,也是操作系统可以控制的最小单位,在数据科学中很多涉及大量计算、CPU密集型的任务都可以通过多进程并行运算的方式大幅度提升运算效率从而节省时间开销,而在Python中实现多进程有多种方式,本文就将针对其中较为易用的几种方式进行介绍。

二、利用multiprocessing实现多进程

  multiprocessingPython自带的用于管理进程的模块,通过合理地利用multiprocessing,我们可以充分榨干所使用机器的CPU运算性能,在multiprocessing中实现多进程也有几种方式。

2.1 Process

  Processmultiprocessing中最基础的类,用于创建进程,先来看看下面的示例:

single_process.py

import multiprocessing
import datetime
import numpy as np
import os def job(): print(f'进程{os.getpid()}开始计算:', datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
for j in range(100):
_ = np.sum(np.random.rand(10000000))
print(f'进程{os.getpid()}结束运算:', datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')) if __name__ == '__main__': process = multiprocessing.Process(target=job)
process.start()


图1 single_process.py运行结果

  在上面的例子中,我们首先定义了函数job(),其连续执行一项运算任务100次,并在开始和结束的时刻打印该进程对应的pid,用来唯一识别一个独立的进程,接着利用Process()将一个进程实例化,其主要参数如下:

target: 需要执行的运算函数

args: target函数对应的传入参数,元组形式传入

  在process创建完成之后,我们对其调用.start()方法执行运算,这样我们就实现了单个进程的创建与使用,在此基础上,我们将上述例子多线程化:

multi_processes.py

import multiprocessing
import datetime
import numpy as np
import os def job(): print(f'进程{os.getpid()}开始计算:', datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
for j in range(100):
_ = np.sum(np.random.rand(10000000))
print(f'进程{os.getpid()}结束运算:', datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')) if __name__ == '__main__': process_list = [] for i in range(multiprocessing.cpu_count() - 1):
process = multiprocessing.Process(target=job)
process_list.append(process) for process in process_list:
process.start() for process in process_list:
process.join()


图2 multi_processes.py运行结果

  在上面的例子中,我们首先初始化用于存放多个线程的列表process_list,接着用循环的方式创建了CPU核心数-1个进程并添加到process_list中,再接着用循环的方式将所有进程逐个激活,最后使用到.join()方法,这个方法用于控制进程之间的并行,如下例:

join_demo.py

import multiprocessing
import os
import datetime
import time def job(): print(f'进程{os.getpid()}开始:', datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
time.sleep(5)
print(f'进程{os.getpid()}结束:', datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')) if __name__ == '__main__': process1 = multiprocessing.Process(target=job)
process2 = multiprocessing.Process(target=job) process1.start()
process1.join() process2.start()
process2.join()
print('='*200)
process3 = multiprocessing.Process(target=job)
process4 = multiprocessing.Process(target=job) process3.start()
process4.start() process3.join()
process4.join()


图2 multi_processes.py运行结果

  观察对应进程执行的开始结束时间信息可以发现,一个进程对象在.start()之后,若在其他的进程对象.start()之前调用.join()方法,则必须等到先前的进程对象运行结束才会接着执行.join()之后的非.join()的内容,即前面的进程阻塞了后续的进程,这种情况下并不能实现并行的多进程,要想实现真正的并行,需要现行对多个进程执行.start(),接着再对这些进程对象执行.join(),才能使得各个进程之间相互独立,了解了这些我们就可以利用Process来实现多进程运算;

2.2 Pool

  除了上述的Process,在multiprocessing中还可以使用Pool来快捷地实现多进程,先来看下面的例子:

Pool_demo.py

from multiprocessing import Pool
import numpy as np
from pprint import pprint def job(n):
return np.mean(np.random.rand(n)), np.std(np.random.rand(n)) if __name__ == '__main__':
with Pool(5) as p:
pprint(p.map(job, [i**10 for i in range(1, 6)]))


图3 Pool_demo.py运行结果

  在上面的例子中,我们使用Pool这个类,将自编函数job利用.map()方法作用到后面传入序列每一个位置上,与Python自带的map()函数相似,不同的是map()函数将传入的函数以串行的方式作用到传入的序列每一个元素之上,而Pool()中的.map()方法则根据前面传入的并行数量5,以多进程并行的方式执行,大大提升了运算效率。

三、利用joblib实现多进程

  与multiprocessing需要将执行运算的语句放置于含有if name == 'main':的脚本文件中下不同,joblib将多进程的实现方式大大简化,使得我们可以在IPython交互式环境下中灵活地使用它,先看下面这个例子:

from joblib import Parallel, delayed
import numpy as np
import time
import datetime def job(i):
start = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
time.sleep(5)
end = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') return start, end result = Parallel(n_jobs=5, verbose=1)(delayed(job)(j) for j in range(5))
result


图4 joblib并行示例

  在上面的例子中,我们从joblib中导入Paralleldelayed,仅用Parallel(n_jobs=5, verbose=1)(delayed(job)(j) for j in range(5))一句就实现了并行运算的功能,其中n_jobs控制并行进程的数量,verbose参数控制是否打印进程运算过程,如果你熟悉scikit-learn,相信这两个参数你一定不会陌生,因为scikit-learnRandomForestClassifier等可以并行运算的算法都是通过joblib来实现的。

  以上就是本文的全部内容,如有笔误望指出!

(数据科学学习手札70)面向数据科学的Python多进程简介及应用的更多相关文章

  1. (数据科学学习手札18)二次判别分析的原理简介&Python与R实现

    上一篇我们介绍了Fisher线性判别分析的原理及实现,而在判别分析中还有一个很重要的分支叫做二次判别,本文就对二次判别进行介绍: 二次判别属于距离判别法中的内容,以两总体距离判别法为例,对总体G1,, ...

  2. (数据科学学习手札22)主成分分析法在Python与R中的基本功能实现

    上一篇中我们详细介绍推导了主成分分析法的原理,并基于Python通过自编函数实现了挑选主成分的过程,而在Python与R中都有比较成熟的主成分分析函数,本篇我们就对这些方法进行介绍: R 在R的基础函 ...

  3. (数据科学学习手札20)主成分分析原理推导&Python自编函数实现

    主成分分析(principal component analysis,简称PCA)是一种经典且简单的机器学习算法,其主要目的是用较少的变量去解释原来资料中的大部分变异,期望能将现有的众多相关性很高的变 ...

  4. (数据科学学习手札15)DBSCAN密度聚类法原理简介&Python与R的实现

    DBSCAN算法是一种很典型的密度聚类法,它与K-means等只能对凸样本集进行聚类的算法不同,它也可以处理非凸集. 关于DBSCAN算法的原理,笔者觉得下面这篇写的甚是清楚练达,推荐大家阅读: ht ...

  5. (数据科学学习手札11)K-means聚类法的原理简介&Python与R实现

    kmeans法(K均值法)是麦奎因提出的,这种算法的基本思想是将每一个样本分配给最靠近中心(均值)的类中,具体的算法至少包括以下三个步骤: 1.将所有的样品分成k个初始类: 2.通过欧氏距离将某个样品 ...

  6. (数据科学学习手札09)系统聚类算法Python与R的比较

    上一篇笔者以自己编写代码的方式实现了重心法下的系统聚类(又称层次聚类)算法,通过与Scipy和R中各自自带的系统聚类方法进行比较,显然这些权威的快捷方法更为高效,那么本篇就系统地介绍一下Python与 ...

  7. (数据科学学习手札55)利用ggthemr来美化ggplot2图像

    一.简介 R中的ggplot2是一个非常强大灵活的数据可视化包,熟悉其绘图规则后便可以自由地生成各种可视化图像,但其默认的色彩和样式在很多时候难免有些过于朴素,本文将要介绍的ggthemr包专门针对原 ...

  8. (数据科学学习手札50)基于Python的网络数据采集-selenium篇(上)

    一.简介 接着几个月之前的(数据科学学习手札31)基于Python的网络数据采集(初级篇),在那篇文章中,我们介绍了关于网络爬虫的基础知识(基本的请求库,基本的解析库,CSS,正则表达式等),在那篇文 ...

  9. (数据科学学习手札49)Scala中的模式匹配

    一.简介 Scala中的模式匹配类似Java中的switch语句,且更加稳健,本文就将针对Scala中模式匹配的一些基本实例进行介绍: 二.Scala中的模式匹配 2.1 基本格式 Scala中模式匹 ...

随机推荐

  1. Dockerfile 构建镜像

    一.使用dockerfile构建镜像 基本结构: a.设置基础镜像 当前镜像继承于的基础镜像 FROM centos:latest  b.设置维护者信息 没有固定格式  c.设置需要添加到容器中的文件 ...

  2. .netcore 开发的 iNeuOS 物联网平台部署在 Ubuntu 操作系统,无缝跨平台。助力《2019 中国.NET 开发者峰会》。

    2019 中国.NET 开发者峰会正式启动 目       录 1.      概述... 2 2.      准备运行程序包... 2 3.      安装.netcore. 3 4.      安 ...

  3. 一致性hash (PHP)

    <?php /** * Flexihash - A simple consistent hashing implementation for PHP. * * The MIT License * ...

  4. Bitmap简介

    1.  BitMap Bit-map的基本思想就是用一个bit位来标记某个元素对应的Value,而Key即是该元素.由于采用了Bit为单位来存储数据,因此在存储空间方面,可以大大节省.(PS:划重点 ...

  5. RDD基础-笔记

    RDD编程 基础Spark中的RDD是一个不可变的分布式对象集合.每个RDD都被分为多个分区,这些分区运行在集群中的不同节点上.RDD可以包含Python.java.Scala中任意类型的对象,甚至可 ...

  6. div模拟select/option解决兼容性问题及增加可拓展性

    个人博客: http://mcchen.club 想到做这个模拟的原因是之前使用select>option标签的时候发现没有办法操控option的很多样式,比如line-height等,还会由此 ...

  7. Tomcat8 结构原理解析

    Tomcat是JavaWeb组件架构中一款apache开源的服务器软件,通过对其的学习,总结并且分享了关于它的知识,下边是分享ppt内容,希望对想了解tomcat人有帮助. Tomcat历史 1999 ...

  8. python编程基础之十

    分支条件: 单一分支条件:if 条件 : 条件真运行... 双分支条件:if 条件 : 条件真运行else: 条件假运行... 多分支条件:if 条件1 : 条件1真运行elif 条件2 : 条件1假 ...

  9. netty源码解解析(4.0)-25 ByteBuf内存池:PoolArena-PoolChunk

    PoolArena实现了用于高效分配和释放内存,并尽可能减少内存碎片的内存池,这个内存管理实现使用PageRun/PoolSubpage算法.分析代码之前,先熟悉一些重要的概念: page: 页,一个 ...

  10. Hydra爆破神器使用

    参数详解: -R 根据上一次进度继续破解-S 使用SSL协议连接-s 指定端口-l 指定用户名-L 指定用户名字典(文件)-p 指定密码破解-P 指定密码字典(文件)-e 空密码探测和指定用户密码探测 ...