我正在尝试使用多个线程编写更快的python代码。我不想使用ProcessPoolExecutor
来保留内存消耗。
所以,当我使用ThreadPoolExecutor.map
将迭代器映射到函数时。确实没有用,代码所花费的时间没有得到真正的改善。然后,我了解了python中的GIL,我的问题是:如果将GIL应用于所有人,为什么他们要创建ThreadPoolExecutor.map
,还是有更好的主意使用ThreadPoolExecutor.map
。
[请找到我用来理解此过程的示例。我很高兴听到关于如何将多个线程用于迭代器而不是多个进程的建议,因为我的存储卡和cpus都不那么高。
import concurrent.futures
import math
PRIMES = [
112272535095293,
112582705942171,
112272535095293,
115280095190773,
115797848077099,
1099726899285419]
def is_prime(n):
if n < 2:
return False
if n == 2:
return True
if n % 2 == 0:
return False
sqrt_n = int(math.floor(math.sqrt(n)))
for i in range(3, sqrt_n + 1, 2):
if n % i == 0:
return False
return True
def main():
with concurrent.futures.ThreadPoolExecutor(max_workers = 4) as executor:
future= executor.map(is_prime, PRIMES)
print(future.result())
if __name__ == '__main__':
main()
如您所述,GIL
表示一次只能使用1个CPU,并且只有1个“真实”线程。因此,使用线程池不会加快CPU绑定代码的速度。但是,如果标准库和其他第三方库中的许多函数在I / O上被阻塞,它们会自动释放GIL
。
例如,如果您有代码尝试从Internet下载很多内容,则可以使用Python线程池。当一个线程发出请求下载某些内容并等待响应时,它可以(取决于用于发出HTTP请求的库)释放GIL
并给另一个线程运行的机会。这意味着您可以在许多请求完成之前发出许多请求,然后当它们的响应可用时,将再次唤醒每个Python线程。这种Python多线程可以极大地提高性能。