为什么线程dask示例并行执行
Why is threaded dask example executing in parallel
出于教学目的,我正在尝试使用 dask delayed 创建简单的示例,这些示例在使用线程而不是进程时突出显示 GIL。我现在使用单机调度程序来保持简单。我的理解是从单线程切换到线程不会有任何变化,因为 GIL 应该阻止并行执行。
事实并非如此。当我使用 threaded
选项时,代码仍然比 processes
运行得更快(实际上更快)(单线程=3s,线程=1s,进程=1.7s)。三个延时调用基本同时执行
显然我并不像我想的那样明白发生了什么。有人可以解释这里发生了什么吗?为什么 GIL 没有用线程锁定我的计算?
import time
import dask
from dask import delayed
def func(i):
import time
print(f'Function {i:.0f} starting')
time.sleep(1)
print(f'Function {i:.0f} finished')
lazy = [delayed(func)(i) for i in range(3)]
with dask.config.set(scheduler='processes'): # single-threaded, processes or threads
start = time.time()
dask.compute(lazy)
elaps = time.time() - start
print(elaps)
答案很简单:sleep()
没有 GIL,因为没有什么可做的。您需要设计一些真正的 "work" 以锁定线程并降低并行性。
出于教学目的,我正在尝试使用 dask delayed 创建简单的示例,这些示例在使用线程而不是进程时突出显示 GIL。我现在使用单机调度程序来保持简单。我的理解是从单线程切换到线程不会有任何变化,因为 GIL 应该阻止并行执行。
事实并非如此。当我使用 threaded
选项时,代码仍然比 processes
运行得更快(实际上更快)(单线程=3s,线程=1s,进程=1.7s)。三个延时调用基本同时执行
显然我并不像我想的那样明白发生了什么。有人可以解释这里发生了什么吗?为什么 GIL 没有用线程锁定我的计算?
import time
import dask
from dask import delayed
def func(i):
import time
print(f'Function {i:.0f} starting')
time.sleep(1)
print(f'Function {i:.0f} finished')
lazy = [delayed(func)(i) for i in range(3)]
with dask.config.set(scheduler='processes'): # single-threaded, processes or threads
start = time.time()
dask.compute(lazy)
elaps = time.time() - start
print(elaps)
答案很简单:sleep()
没有 GIL,因为没有什么可做的。您需要设计一些真正的 "work" 以锁定线程并降低并行性。