现在的电脑的CPU一般都有多个核心,在Python中可以使用 multiprocessing 包比较方便地实现将计算任务分配给多个核心,使之并行地计算以实现加速的效果。
一般主要会用到的语法有
获取CPU的核心数:
n_cpu = multiprocessing.cpu_count()
并行执行函数:
proc = multiprocessing.Process(target=single_run, args=(digits, "parallel"))
proc.start()
proc.join()
其中,target属性是要并行执行的函数名,args是该函数的参数,注意要用元组的形式。
下面通过一个简单的例子来演示一下CPU并行地效果。对MINST-digits数据的10个类分别运行t-SNE降维,比较并行运行与串行运行的时间差异。
import numpy as np
import multiprocessing
from sklearn.manifold import TSNE
import time
path = "E:\\blog\\data\\MNIST50m\\"
def run_tsne(data):
t_sne = TSNE(n_components=2, perplexity=30.0)
Y = t_sne.fit_transform(data)
return Y
def single_run(digits, fold="1by1"):
for digit in digits:
print(str(digit) + " starting...")
X = np.loadtxt(path+str(digit)+".csv", dtype=np.float, delimiter=",")
t_sne = TSNE(n_components=2, perplexity=30.0)
Y = t_sne.fit_transform(X)
np.savetxt(path+fold+"\\Y"+str(digit)+".csv", Y, fmt='%f', delimiter=",")
print(str(digit) + " finished.")
def one_by_one():
begin_time = time.time()
digits = [1, 2, 3, 4, 5, 6, 7, 8, 9]
# digits = [1, 2, 3, 4, 5, 6]
single_run(digits, "1by1")
end_time = time.time()
print("one by one time: ", end_time-begin_time)
def parallel():
begin_time = time.time()
n = 10 # 10
procs = []
n_cpu = multiprocessing.cpu_count()
chunk_size = int(n/n_cpu)
for i in range(0, n_cpu):
min_i = chunk_size * i
if i < n_cpu-1:
max_i = chunk_size * (i+1)
else:
max_i = n
digits = []
for digit in range(min_i, max_i):
digits.append(digit)
procs.append(multiprocessing.Process(target=single_run, args=(digits, "parallel")))
for proc in procs:
proc.start()
for proc in procs:
proc.join()
end_time = time.time()
print("parallel time: ", end_time-begin_time)
if __name__ == '__main__':
# one_by_one()
parallel()
串行输出如下,可以看到花了500多秒的时间。
1 starting...
1 finished.
2 starting...
2 finished.
3 starting...
3 finished.
4 starting...
4 finished.
5 starting...
5 finished.
6 starting...
6 finished.
7 starting...
7 finished.
8 starting...
8 finished.
9 starting...
9 finished.
one by one time: 538.7096929550171
而在我六核的 i5-9400F 上的并行输出如下,可以看到花了300多秒,稍微快了一些,但是效果并不理想。
4 starting...
3 starting...
0 starting...
5 starting...
2 starting...
1 starting...
0 finished.
2 finished.
4 finished.
3 finished.
5 finished.
6 starting...
1 finished.
6 finished.
7 starting...
7 finished.
8 starting...
8 finished.
9 starting...
9 finished.
parallel time: 339.75568318367004
为了更好地体现CPU并行和串行的差别,我又让它们分别对6个digit做t-SNE降维,并行的速度大概是串行的4倍。
6个digit的串行输出:
1 starting...
1 finished.
2 starting...
2 finished.
3 starting...
3 finished.
4 starting...
4 finished.
5 starting...
5 finished.
6 starting...
6 finished.
one by one time: 357.5319800376892
6个digit的并行输出:
3 starting...
4 starting...
1 starting...
5 starting...
2 starting...
0 starting...
5 finished.
0 finished.
4 finished.
2 finished.
1 finished.
3 finished.
parallel time: 85.06037616729736
总的来说,对于一些计算需求来讲,CPU多核并行能够提高一定的计算速度,但是提升能力有限,比如6核的i5处理器,速度的提升不会超过6倍。所以如果想大幅度提高速度的话,还是得用GPU版本的并行。
关于Python的GPU编程,可以参考 《Python Parallel Programming Cookbook》这本书,这是一本开源的书,在网上应该能够比较方便地找到电子版。如果实在找不到(或者懒得找)也可以
联系我
获取。
现在的电脑的CPU一般都有多个核心,在Python中可以使用 multiprocessing 包比较方便地实现将计算任务分配给多个核心,使之并行地计算以实现加速的效果。一般主要会用到的语法有获取CPU的核心数:n_cpu = multiprocessing.cpu_count()并行执行函数:proc = multiprocessing.Process(target=sin...
1. 使用原因:
通常现有的计算机都包含多个
CPU
内核,然而,现实中运行程序时,通常仅用到单核
CPU
,导致
CPU
资源无法充分利用。因此,我们可以通过
多核
CPU
并行
计算来加快程序的运行。
2. 使用方法
2.1. 需要用到的功能函数
获取
CPU
的内核数量
cpu
_num = multiprocessing.
cpu
_count()
并行
计算函数
proc = multiprocessing.Process(target=single_run, args=(digits, "paralle
3.2 服务端
横向联邦学习的服务端的主要功能是将被选择的客户端上传的本地模型进行模型聚合。但这里需要特别注意的是,事实上,对于一个功能完善的联邦学习框架,比如我们FATE平台,服务端的功能要复杂得多,比如服务端需要对各个客户端节点进行网络监控、对失败节点发出重连信号等。本章由于是在本地模拟的,不涉及网络通信细节和失败故障等处理,因此不讨论这些功能细节,仅涉及模型聚合功能。
我们将不再独立编写服务端的代码,将服务端蕴含于主函数中。
3.3 客户端
横向联邦学习的客户端主要功能是接收服务端的下发指令和全局模型,利用本地数据进行局部模型训练。与前一节一样,对于一个功能完善的联邦学习框架,客户端的功能同样相当复杂,比如需要考虑本地的资源(
CPU
、内存等)是否满足训练需要、当前的网络中断、当前的训练由于受到外界因素影响而中断等。
1 从执行程序角度
基本的思想是,一个程序,计算机会读入一条指令,然后指向这条指令,同时读取另一条指令,然后执行那条指令,这实际上和正在执行的程序无关(程序可以分解为多条基础指令)。
CPU
提供了这个庞大的硬件基础设施,使程序运行速度比一次只执行一条指令快,即它采用了一种称为超标量乱序执行的技术,你可以认为你的程序是一个顺序执行的执行序列,而
CPU
需要尽可能读取多的指令序列,然后
CPU
会把读入的指令拆开,发现有的指令之间不是相互依赖的,所以我可以开始执行程序后面的代码,而不是当前的代码,因为它们彼此独立,这
文章目录subprocess模块subprocess.run() 函数的使用subprocess.Popen()函数实时获取subprocess子进程的输出多进程multiprocessing为什么要多进程?多进程
实现
方法
进程是资源分配的最小单位,线程是
CPU
调度的最小单位。做个
简单
的比喻:进程=火车,线程=车厢。
subprocess模块
Python
的subprocess模块,用来创建和管理子进程(不是线程),并能够与创建的子进程的stdin,stdout,stderr连接通信,获取子进程执行