我正在运行脚本来获取数据库表的列表,检查每个表的行数,并将每个查询的结果附加到字典中。我使用多处理来加快它的速度:Manager创建一个可共享的列表和可共享的字典,进程可以从中读取和追加,以及Process来设置进程。
from multiprocessing import Process, Manager
def main():
mgr = Manager()
# Function to get the list of tables
table_list = mgr.list(get_table_list())
counts = mgr.dict()
for table in table_list:
# get_table_count runs a 'SELECT COUNT(*) FROM <table>' and appends
# the result to the counts dict
p = Process(target=select_star, args=(table, counts, 'prod'))
p.start()
p.join()
我的问题是,Process如何管理开放流程的数量?我习惯于将pool()与apply_async()方法一起使用,您可以在其中指定实例化池时的进程数。
如果这是用于此应用程序的最佳方法的任何其他评论,也将不胜感激。
-
感谢dano帮助实施以下两种解决方案:
1 - 使用Pool.apply_async,因为我已经习惯了:
from multiprocessing import Process, Manager, cpu_count
def main():
mgr = Manager()
table_list = get_table_list()
pool = Pool(cpu_count() / 2)
prod_counts = mgr.dict()
for table in table_list:
pool.apply_async(get_table_count, args=(table, prod_counts, 'prod'))
pool.close()
pool.join()
2 - 使用带有itertools.partial()
的Pool.map()from multiprocessing import Process, Manager, cpu_count
def main():
mgr = Manager()
table_list = get_table_list()
pool = Pool(cpu_count() / 2)
prod_counts = mgr.dict()
func = partial(get_table_count, result_dict=prod_counts, env='prod')
pool.map(func, table_list)
print prod_counts
答案 0 :(得分:2)
multiprocessing.Process
不知道有多少其他进程是打开的,或者做任何事情来管理正在运行的Process
个对象的数量。您需要使用multiprocessing.Pool
来获取该功能。
如果直接使用Process
,则在致电p.start()
后立即启动子流程,并在致电Process
时等待p.join()
退出。因此,在您的示例代码中,您一次只运行一个进程,但是启动len(table_list)
个不同的进程。
这不是一个好方法;因为你一次只启动一个进程,所以你并没有真正同时做任何事情。由于启动子进程和访问Manager.dict
的开销,这最终会比常规的单线程/进程方法慢。您应该只使用Pool
:
from functools import partial
from multiprocessing import Manager, Pool
def select_star(table, counts, type_): # counts and type_ will always be the counts dict and "prod", respectively
pass
def main():
mgr = Manager()
counts = mgr.dict()
p = Pool()
func = partial(select_star, counts, "prod") # Using a partial lets us pass extra parameters to select_start
p.map(func, get_table_list()) # No need to use a manager for the list, since you're not passing the whole thing to the children.
if __name__ == "__main__":
main()
答案 1 :(得分:1)