代码示例
全部代码示例请参考:
并行处理 Parallel Processing
- 在同一时间处理两个任务,在同一个CPU或多个CPU上运行代码,从而实现加速
线程和进程 Threads and Processes
进程:
- 进程是一个程序的实例,比如Jupyter notebook, Python interpreter。
- 一个进程包括多个线程(子进程)来处理子任务。比如读写、加载HTML网页、储存文件
- 两个进程可以在一个Python程序里同时进行。
- 进程比线程有更多的开销,因为打开和关闭进程需要更多的时间
- 在多个进程之间共享信息比多个线程之间共享信息更慢,因为多个进程之间不共享内存
- 多进程用于CPU密集型任务(CPU intensive tasks),使用多个core,避免GIL锁
线程:
- 线程是子进程,mini-process
- 同一个进程里的线程共享内存空间
- 两个线程不能在一个Python程序中同时运行(因为Python GIL锁)
- 多线程用于IO密集型任务
CPU Core
- CPU或处理器(processor)管理计算机的基本计算工作。
- CPU有一个或多个核,允许CPU同时执行代码
Example
- 注意:在运行多进程代码的时候,需要使用
if __name__ == '__main__':
将代码保护起来,同时也不能在jupyter中直接运行 res = executor.map(func, args)
的输出结果是一个generator的对象,我们可以用list(res)
或者pd.concat(res)
来处理结果。一旦res
被处理过后,就成空的了
test = pd.DataFrame({
"a": [1, 2, 3],
"b": [-1, -2, -3]
})
def process_df(test, n):
cnt = 0
for i in range(10000000):
cnt += 1
return test * cnt * n
def multi_process_df(args):
return process_df(args[0], args[1])
def multiprocessing_df(func, args, workers):
begin_time = time.time()
with ProcessPoolExecutor(max_workers=workers) as executor:
res = executor.map(func, args)
print("multi res", res)
# print("multi res list", list(res))
# print("multi res concat", pd.concat(res))
return res
if __name__ == "__main__":
start_time = time.time()
args = [(test, i) for i in range(8)]
res = multiprocessing_df(multi_process_df, args, 4)
print("res next:", next(res))
print(time.time() - start_time)
一些concurrent package的实例,详细请查看
LightGBM多进程
用LightGBM做预测的时候,默认是用全部的cores,因此通过自己写的multiprocess来提速是没有用的。可以手动调整预测所用的core的数量model.predict(X, n_jobs=1)
,这种情况下multiprocess才有用。
Reference:
- https://engineering.contentsquare.com/2018/multithreading-vs-multiprocessing-in-python/#:~:text=Multithreading%20is%20concurrency.,Multiprocessing%20is%20best%20for%20computations.
- https://medium.com/@bfortuner/python-multithreading-vs-multiprocessing-73072ce5600b
- https://stackoverflow.com/questions/15900366/all-example-concurrent-futures-code-is-failing-with-brokenprocesspool
- https://stackoverflow.com/questions/47313732/jupyter-notebook-never-finishes-processing-using-multiprocessing-python-3