Os.sched_getapherity(0)与os.cpu_count()
问题描述
所以,我知道标题中这两种方法的区别,但不知道实际意义。
据我所知:如果您使用的NUM_Worker多于实际可用的内核,您将面临巨大的性能下降,因为您的操作系统不断来回切换以保持并行。我不知道这是不是真的,但我是从某个比我聪明的人那里读到的。
在os.cpu_count()
的文档中写着:
返回系统的CPU数量。如果未确定,则返回NONE。此数量不等于 当前进程可以使用。可以获得可用的CPU数量 WITH len(os.sched_getapherity(0))
因此,如果某个进程可以使用的CPU比系统中的CPU多,那么我想知道系统指的是什么。
我只想安全高效地实现multiprocessing.pool
功能。所以我的问题总结如下:
:
NUM_WORKERS = os.cpu_count() - 1
# vs.
NUM_WORKERS = len(os.sched_getaffinity(0)) - 1
-1
是因为我发现,如果我尝试在处理数据的同时工作,我的系统延迟会小很多。
解决方案
如果您的任务是纯100%受CPU限制的,即只做计算,那么显然,如果进程池大小大于计算机上可用的CPU数量,则不会/不会获得任何好处。但是,如果有I/O的混合,进程将放弃CPU,等待I/O完成(或者,例如,从网站返回URL,这需要相对较长的时间),该怎么办?在我看来,在这种情况下,如果进程池大小超过os.cpu_count()
,您是否无法实现更高的吞吐量,这一点我不清楚。
更新
以下是演示这一点的代码。这段代码使用的是进程,使用线程处理可能是最好的选择。我的台式机上有8个内核。该程序只需同时检索54个URL(在本例中为并行检索)。向程序传递一个参数,即要使用的池的大小。遗憾的是,仅创建其他进程就会产生初始开销,因此如果您创建了太多进程,节省的成本就会开始下降。但是,如果任务长时间运行并且有大量I/O,那么创建进程的开销最终将是值得的:
from concurrent.futures import ProcessPoolExecutor, as_completed
import requests
from timing import time_it
def get_url(url):
resp = requests.get(url, headers={'user-agent': 'my-app/0.0.1'})
return resp.text
@time_it
def main(poolsize):
urls = [
'https://ibm.com',
'https://microsoft.com',
'https://google.com',
'https://ibm.com',
'https://microsoft.com',
'https://google.com',
'https://ibm.com',
'https://microsoft.com',
'https://google.com',
'https://ibm.com',
'https://microsoft.com',
'https://google.com',
'https://ibm.com',
'https://microsoft.com',
'https://google.com',
'https://ibm.com',
'https://microsoft.com',
'https://google.com',
'https://ibm.com',
'https://microsoft.com',
'https://google.com',
'https://ibm.com',
'https://microsoft.com',
'https://google.com',
'https://ibm.com',
'https://microsoft.com',
'https://google.com',
'https://ibm.com',
'https://microsoft.com',
'https://google.com',
'https://ibm.com',
'https://microsoft.com',
'https://google.com',
'https://ibm.com',
'https://microsoft.com',
'https://google.com',
'https://ibm.com',
'https://microsoft.com',
'https://google.com',
'https://ibm.com',
'https://microsoft.com',
'https://google.com',
'https://ibm.com',
'https://microsoft.com',
'https://google.com',
'https://ibm.com',
'https://microsoft.com',
'https://google.com',
'https://ibm.com',
'https://microsoft.com',
'https://google.com',
'https://ibm.com',
'https://microsoft.com',
'https://google.com',
]
with ProcessPoolExecutor(poolsize) as executor:
futures = {executor.submit(get_url, url): url for url in urls}
for future in as_completed(futures):
text = future.result()
url = futures[future]
print(url, text[0:80])
print('-' * 100)
if __name__ == '__main__':
import sys
main(int(sys.argv[1]))
8进程:(我的核数):
func: main args: [(8,), {}] took: 2.316840410232544 sec.
16个进程:
func: main args: [(16,), {}] took: 1.7964842319488525 sec.
24个进程:
func: main args: [(24,), {}] took: 2.2560818195343018 sec.
相关文章