如果在存在GIL的情况下,在多线程程序中执行的所有子任务是顺序发生的,则它等效于单线程程序。为什么用Python编写多线程程序包(multiprocessing.dummy.Pool,multiprocessing.pool.ThreadPool,并发.futures.ThreadPoolExecutor等)?为什么有人要使用它们? (这与多重处理无关)
答案 0 :(得分:1)
两件事:
GIL会不时释放。例如,当您尝试执行一些冗长的操作(从文件读取,写入文件,通过网络发送等等)时。这样可以进行一些交错操作-在一个线程中读取,在另一个线程中处理。
多线程处理不仅具有性能,还具有其他好处-例如易于表达。假设您有两种“并行”运行的算法,它们相互通信并交换数据。您将每种算法放在自己的线程上,进行同步(以确保在可能的时候进行线程切换),然后关闭。如果没有多线程,您将不得不依赖事件编程,这很难且易于扩展。一个很好的例子是各种基于会话的服务器,例如ftp服务器。编写多线程多用户ftp服务器比单线程要容易得多。
通常,是的,如果使用线程执行性能,则python的线程没有意义。但是python不是用来提高性能的,而是用来编写(和修改)代码的简单程度。线程确实对并行代码有很大帮助,即使它们没有提供多线程性能优势。
答案 1 :(得分:0)
multiprocessing.Pool实际上以并行方式运行代码。
文档说明
多处理程序包提供本地和远程并发, 通过使用有效地回避了全局解释器锁定 子进程而不是线程。因此,多处理 模块允许程序员充分利用多个处理器 给定的机器。
尝试一下,check the docs以获取更多信息!
from multiprocessing import Pool
import time
def f(n):
print('start sleeping')
time.sleep(4)
print('slept enough')
return n*2
s = time.time()
with Pool(4) as p:
r = p.map(f, [1,2,3,4])
print(f'multiprocessing version runtime: {round(time.time()-s,2)} seconds')
print(r)
s = time.time()
r=[]
for n in [1,2,3,4]:
r.append(f(n))
print(f'loop version runtime: {round(time.time()-s,2)} seconds')
print(r)
输出:
start sleeping
start sleeping
start sleeping
start sleeping
slept enough
slept enough
slept enough
slept enough
multiprocessing version runtime: 4.03 seconds
[2, 4, 6, 8]
start sleeping
slept enough
start sleeping
slept enough
start sleeping
slept enough
start sleeping
slept enough
loop version runtime: 16.01 seconds
[2, 4, 6, 8]