python 中的 ThreadPoolExecutor 是否真的有效
Does ThreadPoolExecutor in python really work
我正在尝试使用多线程编写更快的 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 个 "real" 线程。所以使用线程池不会加速 CPU-bound 代码。但是,标准库和其他 3rd 方库中的许多函数如果在 I/O.
上被阻止,将自动释放 GIL
例如,如果您有代码试图从互联网上下载很多东西,您可以使用 Python 线程池。当一个线程请求下载某些东西并等待响应时,它可以(取决于您使用什么库来发出 HTTP 请求)释放 GIL
并给另一个线程一个机会 运行。这意味着您可以在任何请求完成之前发出许多请求,然后每个 Python 线程将在响应可用时再次被唤醒。这种 Python 多线程可以带来巨大的性能提升。
我正在尝试使用多线程编写更快的 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 个 "real" 线程。所以使用线程池不会加速 CPU-bound 代码。但是,标准库和其他 3rd 方库中的许多函数如果在 I/O.
GIL
例如,如果您有代码试图从互联网上下载很多东西,您可以使用 Python 线程池。当一个线程请求下载某些东西并等待响应时,它可以(取决于您使用什么库来发出 HTTP 请求)释放 GIL
并给另一个线程一个机会 运行。这意味着您可以在任何请求完成之前发出许多请求,然后每个 Python 线程将在响应可用时再次被唤醒。这种 Python 多线程可以带来巨大的性能提升。