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

本文对应脚本已上传至我的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来实现的。

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

原文地址:https://www.cnblogs.com/feffery/p/11621076.html

时间: 2024-11-05 23:38:28

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

(数据科学学习手札32)Python中re模块的详细介绍

一.简介 关于正则表达式,我在前一篇(数据科学学习手札31)中已经做了详细介绍,本篇将对Python中自带模块re的常用功能进行总结: re作为Python中专为正则表达式相关功能做出支持的模块,提供了一系列方法来完成几乎全部类型的文本信息的处理工作,下面一一介绍: 二.re.compile() 在前一篇文章中我们使用过这个方法,它通过编译正则表达式参数,来返回一个目标对象的匹配模式,进而提高了正则表达式的效率,主要参数如下: pattern:输入的欲编译正则表达式,需将正则表达式包裹在''内传

(数据科学学习手札47)基于Python的网络数据采集实战(2)

一.简介 马上大四了,最近在暑期实习,在数据挖掘的主业之外,也帮助同事做了很多网络数据采集的内容,接下来的数篇文章就将一一罗列出来,来续写几个月前开的这个网络数据采集实战的坑. 二.马蜂窝评论数据采集实战 2.1 数据要求 这次我们需要采集的数据是知名旅游网站马蜂窝下重庆区域内所有景点的用户评论数据,如下图所示: 思路是,先获取所有景点的poi ID,即每一个景点主页url地址中的唯一数字: 这一步和(数据科学学习手札33)基于Python的网络数据采集实战(1)中做法类似,即在下述界面: 翻页

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

一.简介 R中的ggplot2是一个非常强大灵活的数据可视化包,熟悉其绘图规则后便可以自由地生成各种可视化图像,但其默认的色彩和样式在很多时候难免有些过于朴素,本文将要介绍的ggthemr包专门针对原生ggplot2图像进行美化,掌握它之后你就可以创作出更具特色和美感的数据可视化作品. 二.基础内容 2.1 安装 不同于常规的R包,ggthemr并没有在CRAN上发布,因此我们需要使用devtools中的install_github()直接从github上安装它,参照github上ggthemr

(数据科学学习手札19)R中基本统计分析技巧总结

在获取数据,并且完成数据的清洗之后,首要的事就是对整个数据集进行探索性的研究,这个过程中会利用到各种描述性统计量和推断性统计量来初探变量间和变量内部的基本关系,本篇笔者便基于R,对一些常用的数据探索方法进行总结: 1.描述性统计量部分 1.1 计算描述性统计量的常规方法 summary() summary()函数提供了最小值.最大值.四分位数和数值型变量的均值,以及因子向量和逻辑型向量的频数统计: > #挂载鸢尾花数据 > data(iris) > #计算鸢尾花各变量的基本描述统计量 &

Python学习系列 (第一章):Python 的简介

一: Python 的简介: python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言的一种继承. 二:Python的应用领域: web 开发: Django\pyramid\Tornado\Bottle\Flask\WebPy 网络编程: twisted\Requests\scrapy\paramiko 科学运算: Scipy\pandas\lpython GUI图形开

(数据科学学习手札81)conda+jupyter玩转数据科学环境搭建

本文示例yaml文件已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 我们在使用Python进行数据分析时,很多时候都在解决环境搭建的问题,不同版本.依赖包等问题经常给数据科学工作流的搭建和运转带来各种各样令人头疼的问题,本文就将基于笔者自己摸索出的经验,以geopandas环境的搭建为例,教你使用conda+jupyter轻松搞定环境的搭建.管理与拓展. 图1 2 虚拟环境的搭建与使用 2.1 使用con

(数据科学学习手札23)决策树分类原理详解&Python与R实现

决策树(Decision Tree)是在已知各种情况发生概率的基础上,通过构成决策树来求取净现值的期望值大于等于零的概率,评价项目风险,判断其可行性的决策分析方法,是直观运用概率分析的一种图解法.由于这种决策分支画成图形很像一棵树的枝干,故称决策树.在机器学习中,决策树是一个预测模型,他代表的是对象属性与对象值之间的一种映射关系. 一.初识决策树 决策树是一种树形结构,一般的,一棵决策树包含一个根结点,若干个内部结点和若干个叶结点: 叶结点:树的一个方向的最末端,表示结果的输出: 根结点:初始样

(数据科学学习手札39)RNN与LSTM基础内容详解

一.简介 循环神经网络(recurrent neural network,RNN),是一类专门用于处理序列数据(时间序列.文本语句.语音等)的神经网络,尤其是可以处理可变长度的序列:在与传统的时间序列分析进行比较的过程之中,RNN因为其梯度弥散等问题对长序列表现得不是很好,而据此提出的一系列变种则展现出很明显的优势,最具有代表性的就是LSTM(long short-term  memory),而本文就从标准的循环神经网络结构和原理出发,再到LSTM的网络结构和原理,对其有一个基本的认识和阐述:

(数据科学学习手札62)详解seaborn中的kdeplot、rugplot、distplot与jointplot

一.简介 seaborn是Python中基于matplotlib的具有更多可视化功能和更优美绘图风格的绘图模块,当我们想要探索单个或一对数据分布上的特征时,可以使用到seaborn中内置的若干函数对数据的分布进行多种多样的可视化,本文以jupyter notebook为编辑工具,针对seaborn中的kdeplot.rugplot.distplot和jointplot,对其参数设置和具体用法进行详细介绍. 二.kdeplot seaborn中的kdeplot可用于对单变量和双变量进行核密度估计并