我有Python
代码:
from multiprocessing import Process
def f(name):
print 'hello', name
if __name__ == '__main__':
for i in range(0, MAX_PROCESSES):
p = Process(target=f, args=(i,))
p.start()
运行良好。但是,MAX_PROCESSES
是可变的,可以是1
和512
之间的任何值。由于我只在具有8
核心的计算机上运行此代码,因此我需要确定是否可以限制允许同时运行的进程数。我调查了multiprocessing.Queue
,但它看起来并不像我需要的那样 - 或许我正在错误地解释文档。
有没有办法限制同时multiprocessing.Process
的同时运行?
答案 0 :(得分:76)
使用multiprocessing.Pool
最合理的做法是根据系统上可用的最大内核数量生成一个工作进程池,然后在内核可用时基本上提供任务。
标准文档(http://docs.python.org/2/library/multiprocessing.html#using-a-pool-of-workers)中的示例显示您还可以手动设置核心数量:
from multiprocessing import Pool
def f(x):
return x*x
if __name__ == '__main__':
pool = Pool(processes=4) # start 4 worker processes
result = pool.apply_async(f, [10]) # evaluate "f(10)" asynchronously
print result.get(timeout=1) # prints "100" unless your computer is *very* slow
print pool.map(f, range(10)) # prints "[0, 1, 4,..., 81]"
如果您的代码需要,还可以通过multiprocessing.cpu_count()
方法计算给定系统上的核心数量,这也很方便。
编辑:这里有一些似乎适合您特定案例的草案代码:
import multiprocessing
def f(name):
print 'hello', name
if __name__ == '__main__':
pool = multiprocessing.Pool() #use all available cores, otherwise specify the number you want as an argument
for i in xrange(0, 512):
pool.apply_async(f, args=(i,))
pool.close()
pool.join()
答案 1 :(得分:2)
更一般而言,它也可能像这样:
import multiprocessing
def chunks(l, n):
for i in range(0, len(l), n):
yield l[i:i + n]
numberOfThreads = 4
if __name__ == '__main__':
jobs = []
for i, param in enumerate(params):
p = multiprocessing.Process(target=f, args=(i,param))
jobs.append(p)
for i in chunks(jobs,numberOfThreads):
for j in i:
j.start()
for j in i:
j.join()
当然,这种方式非常残酷(因为它等待垃圾中的每个进程,直到它继续下一个块为止)。仍然可以在大约相等的函数调用运行时间上很好地工作。
答案 2 :(得分:2)
我认为Semaphore是您要寻找的东西,它计数到0后将阻塞主进程。示例代码:
from multiprocessing import Semaphore
def f(name, sema):
print 'hello', name
sema.release()
if __name__ == '__main__':
concurrency = 20
total_task_num = 1000
sema = Semaphore(concurrency)
all_processes = []
for i in range(total_task_num):
# once `concurrency` processes are running,
# the following code will block main process
sema.acquire()
p = Process(target=f, args=(i, sema))
all_processes.append(p)
p.start()
# inside main process, wait for all processes to finish
for p in all_processes:
p.join()
另一种方法可能会使代码看起来更加结构化,但是如果total_task_num
非常大,则会消耗过多的资源,如下所示:
from multiprocessing import Semaphore
def f(name, sema):
sema.acquire()
print 'hello', name
sema.release()
if __name__ == '__main__':
concurrency = 20
total_task_num = 1000
sema = Semaphore(concurrency)
all_processes = []
for i in range(total_task_num):
p = Process(target=f, args=(i, sema))
all_processes.append(p)
p.start()
# inside main process, wait for all processes to finish
for p in all_processes:
p.join()
以上代码将创建total_task_num
个进程,但只有concurrency
个进程将在其他进程被阻止时运行。