有人可以解释为什么CODE 1优于CODE2,反之亦然:
某些数据: 4核的计算机,并且需要执行 8个独立任务,每个数据需要大量处理,循环,计算等:
代码1:进程+线程
results = multiprocessing.Queue()
p1 = multiprocessing.Process(target=bigTask1, args=(some_arguments, results))
p2 = multiprocessing.Process(target=bigTask2, args=(some_arguments, results))
p3 = multiprocessing.Process(target=bigTask3, args=(some_arguments, results))
p4 = multiprocessing.Process(target=bigTask4, args=(some_arguments, results))
p5 = threading.Thread(target=bigTask5, args=(some_arguments, results))
p6 = threading.Thread(target=bigTask6, args=(some_arguments, results))
p7 = threading.Thread(target=bigTask7, args=(some_arguments, results))
p8 = threading.Thread(target=bigTask8, args=(some_arguments, results))
p1.daemon = True
p2.daemon = True
p3.daemon = True
p4.daemon = True
p5.daemon = True
p6.daemon = True
p7.daemon = True
p8.daemon = True
p1.start()
p2.start()
p3.start()
p4.start()
p5.start()
p6.start()
p7.start()
p8.start()
pool_pr += [p1]
pool_pr += [p2]
pool_pr += [p3]
pool_pr += [p4]
pool_pr += [p5]
pool_pr += [p6]
pool_pr += [p7]
pool_pr += [p8]
for p in pool_pr:
p.join()
代码2:仅处理
results = multiprocessing.Queue()
p1 = multiprocessing.Process(target=bigTask1, args=(some_arguments, results))
p2 = multiprocessing.Process(target=bigTask2, args=(some_arguments, results))
p3 = multiprocessing.Process(target=bigTask3, args=(some_arguments, results))
p4 = multiprocessing.Process(target=bigTask4, args=(some_arguments, results))
p5 = multiprocessing.Process(target=bigTask5, args=(some_arguments, results))
p6 = multiprocessing.Process(target=bigTask6, args=(some_arguments, results))
p7 = multiprocessing.Process(target=bigTask7, args=(some_arguments, results))
p8 = multiprocessing.Process(target=bigTask8, args=(some_arguments, results))
p1.daemon = True
p2.daemon = True
p3.daemon = True
p4.daemon = True
p5.daemon = True
p6.daemon = True
p7.daemon = True
p8.daemon = True
p1.start()
p2.start()
p3.start()
p4.start()
p5.start()
p6.start()
p7.start()
p8.start()
pool_pr += [p1]
pool_pr += [p2]
pool_pr += [p3]
pool_pr += [p4]
pool_pr += [p5]
pool_pr += [p6]
pool_pr += [p7]
pool_pr += [p8]
for p in pool_pr:
p.join()
我主要担心的是,如果我只有4个内核可用,那么使用4个进程+ 4个线程可以获得任何好处吗?是否最好每次强制所有4个核心工作(4个进程)+(4个进程)?
答案 0 :(得分:1)
如果你没有内存限制,那么我会使用CODE 2.它更简单,如果你可以在另一台计算机上运行它,可以扩展到8个核心。
答案 1 :(得分:1)
取决于您是否有超线程或者您正在使用硬盘。
如果你有超线程,8个进程比4快,因为你可以同时运行它们。但是,在这种情况下不要使用线程。
如果您使用硬盘或其他慢速存储介质,您可以使用线程并获得更多吞吐量,因为线程可以在等待获取数据时进行切换。
如果你没有,我会工作,让python处理剩下的工作。
答案 2 :(得分:1)
我觉得,你误解了multiprocessing.Process模式。这并不意味着你将“bigTask1”管理到第一个处理器而将“bigTask2”管理到第二个处理器。这意味着python要求内核在可访问的处理器上分配工作负载,而不是将线程添加到运行GIL的一个处理器的堆中。无论如何,分布在不同的处理器上并不便宜,因为你需要更多的开销来重新同步,重新整合结果......
因此,您需要测试两种方法来查找,这样可以更快/更少资源。很有可能,它会变成多处理.Process不如运行所有使用线程有效。
答案 3 :(得分:1)
"每个需要大量的处理,循环,计算等等#34;
鉴于此,由于GIL,你根本不应该使用线程。您的线程中只有一个会一次执行,因此您无法获得任何性能优势。正如其他人所说的那样,线程仅在您主要进行I / O时才有用。
使用multiprocessing.Process
将允许您正确地扩展所有可用的CPU,这是您想要的。但是,它还会增加启动进程的开销,以及复制需要发送给父进程和子进程之间的工作者的数据。根据您需要在每个工作人员中完成的工作需要多长时间以及需要复制多少数据,数据复制开销有时最终会成为程序中最慢的部分,从而导致multiprocessing
比以单线程/进程方式进行计算要慢。
此外,您可能会或可能不会看到使用8个进程而不是使用4的好处。正如其他人所说,这取决于您是否拥有超线程处理器。在这种情况下,我建议使用multiprocessing.Pool
而不是八个multiprocessing.Process
对象,以便您可以轻松地在4到8个进程之间切换,并衡量程序对每个数字的执行方式:
pool = multiprocessing.Pool(4) # or 8. Try both.
out_list = []
targets = [bigTask1, bigTask2, bigTask3, bigTask4,
bigTask5, bigTask6, bigTask6, bigTask8]
for t in targets:
out_list.append(pool.apply_async(t, args=(some_arguments))
# You don't need a queue if you're using a pool. Just `return`
# the result from the worker function.
results = [r.get() for r in out_list]