1.由cpu利用率来看python进程和线程的区别
见图1.1。其中oracle的导入进程占用了880%多的cpu,而其他python进程才占99%多。这是由于oracle使用了多线程处理,利用了cpu的多个核心进行处理,所有cpu使用率高。
(图1.1)
那么,如果我们python进程也使用多线程是不是也可以提高cpu的使用率,进而减少程序运行时间。
答案是否定的,python由于GIL的存在,多线程的使用和单线程没多大区别,所以即使使用多线程,也只能占用cpu的一个核心。
Python中多线程的替换方案为使用多进程,即使用python中multiprocessing包。使用多进程后,效果如图2.2。可见,每个进程占用20%的cpu,cpu总共使用率已经能达到89%
(图2.2)
2.项目中代码大致实现
要点:
- 进程中尽量不共享可变变量。只共享全局静态变量
- 将需要处理的数据,按进程数分批,作为参数传入进程
- 在全进程处理完后,将处理结果合并
# 进程参数
process_num = config.getint("process","process_num")
process_param_list = list()
process_list = list()
#每个进程处理数量
deal_num = df_discnt.shape[0] / process_num
deal_index = 0
temp_list = list()
#将处理的数据按进程数分成多个部分
for i,discnt_code in enumerate(df_discnt.loc[:,'DISCNT'].unique()):
if deal_index < deal_num:
temp_list.append(discnt_code)
deal_index = deal_index + 1
else:
deal_index = 0
process_param_list.append(temp_list)
# list为引用,需重新创建新list不然会互相修改
temp_list = list()
process_param_list.append(temp_list)
i = 0
for process_param in process_param_list:
i = i + 1
#将多进程加入列表
process_list.append(multiprocessing.Process(target=process_fun, args=(process_param, i)))
#truncate file before program process start
out_dir=get_dir_path("out/temp")
for file in os.listdir(out_dir):
removeFile(out_dir,file)
for process in process_list:
process.daemon = True
process.start()
for process in process_list:
process.join()
merge_file() #合并各个进程处理后的文件