Python - 我应该在 ThreadPoolExecutor 中使用作为参数 ("max_amount_of_threads" - 1) 吗?
Python - Should I use in ThreadPoolExecutor as an argument ("max_amount_of_threads" - 1)?
在我的应用程序中,我正在使用此代码:
executor = ThreadPoolExecutor(5)
executor.submit(partial(self.determine_file_type, text_file_path))
作为一种在我导入文件时不冻结我的应用程序的方法。它运行良好,但我开始怀疑。
如果我对这个 ThreadPoolExecutor 和任何 CPU 中的线程的理解是正确的,那么最好不要使用 5
作为参数,而是使用类似 ("max_amount_of_threads" - 1)?
我听说 python 可以在给定的机器上实际获得线程数量,但我想知道它是否适用于所有 cpus?包括 android 上的移动设备?这是明智之举还是我错了?
编辑:
当前代码:
try:
thread_count = len(os.sched_getaffinity(0)) - 1 if len(os.sched_getaffinity(0)) > 3 else 3
except (AttributeError, NotImplementedError):
thread_count = os.cpu_count() - 1 if os.cpu_count() > 3 else 3
有几个选项:
os.cpu_count()
- 获取系统上 CPU 的数量,并不总是有效,returns None
在这种情况下
multiprocessing.cpu_count()
- 相同,但引发异常而不是返回 None
len(os.sched_getaffinity(0))
- 这会告诉您有多少 usable CPU 可用(当进程的亲和力仅限于核心子集时)。当功能不可用时可以提高 NotImplementedError
。
如果你想自动缩放,我建议尝试#3,如果失败则捕获异常并尝试#1/#2,如果失败,使用一些小的合理的硬编码线程数。或者完全省略参数并让 ThreadPoolExecutor
决定启动多少线程(它通常选择一个略高于内核数量的数字,因为线程被假定为 I/O 绑定并且其中大部分是预期的将大部分时间花在 I/O 上,而不是试图消耗核心;从 3.8/3.9 开始,它使用 min(32, os.cpu_count() + 4)
,但之前已经改变了)。鉴于 GIL,内核的数量通常无关紧要;你要么 I/O 绑定(并且核心不征税),要么 CPU 绑定在 Python 代码中(GIL 将你限制为一个核心)。唯一的例外是在执行繁重的 CPU 工作时释放 GIL 的扩展模块,而您的情况并非如此。
在我的应用程序中,我正在使用此代码:
executor = ThreadPoolExecutor(5)
executor.submit(partial(self.determine_file_type, text_file_path))
作为一种在我导入文件时不冻结我的应用程序的方法。它运行良好,但我开始怀疑。
如果我对这个 ThreadPoolExecutor 和任何 CPU 中的线程的理解是正确的,那么最好不要使用 5
作为参数,而是使用类似 ("max_amount_of_threads" - 1)?
我听说 python 可以在给定的机器上实际获得线程数量,但我想知道它是否适用于所有 cpus?包括 android 上的移动设备?这是明智之举还是我错了?
编辑:
当前代码:
try:
thread_count = len(os.sched_getaffinity(0)) - 1 if len(os.sched_getaffinity(0)) > 3 else 3
except (AttributeError, NotImplementedError):
thread_count = os.cpu_count() - 1 if os.cpu_count() > 3 else 3
有几个选项:
os.cpu_count()
- 获取系统上 CPU 的数量,并不总是有效,returnsNone
在这种情况下multiprocessing.cpu_count()
- 相同,但引发异常而不是返回None
len(os.sched_getaffinity(0))
- 这会告诉您有多少 usable CPU 可用(当进程的亲和力仅限于核心子集时)。当功能不可用时可以提高NotImplementedError
。
如果你想自动缩放,我建议尝试#3,如果失败则捕获异常并尝试#1/#2,如果失败,使用一些小的合理的硬编码线程数。或者完全省略参数并让 ThreadPoolExecutor
决定启动多少线程(它通常选择一个略高于内核数量的数字,因为线程被假定为 I/O 绑定并且其中大部分是预期的将大部分时间花在 I/O 上,而不是试图消耗核心;从 3.8/3.9 开始,它使用 min(32, os.cpu_count() + 4)
,但之前已经改变了)。鉴于 GIL,内核的数量通常无关紧要;你要么 I/O 绑定(并且核心不征税),要么 CPU 绑定在 Python 代码中(GIL 将你限制为一个核心)。唯一的例外是在执行繁重的 CPU 工作时释放 GIL 的扩展模块,而您的情况并非如此。