Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 多处理:仅使用物理内核?_Python_Linux_Parallel Processing_Python Multiprocessing - Fatal编程技术网

Python 多处理:仅使用物理内核?

Python 多处理:仅使用物理内核?,python,linux,parallel-processing,python-multiprocessing,Python,Linux,Parallel Processing,Python Multiprocessing,我有一个函数foo,它消耗了大量内存,我想并行运行几个实例 假设我有一个有4个物理核的CPU,每个物理核有两个逻辑核 我的系统有足够的内存来容纳4个并行的foo,但不能容纳8个。此外,由于这8个核中有4个是逻辑核,因此我也不希望使用全部8个核将带来比仅使用4个物理核更多的收益 所以我只想在4个物理内核上运行foo。换句话说,我想确保执行多处理.Pool(4)(4是由于内存限制,我在这台机器上可以容纳的函数的最大并发运行次数)将作业分派给四个物理核(而不是,例如,两个物理核及其两个逻辑子核的组合)

我有一个函数
foo
,它消耗了大量内存,我想并行运行几个实例

假设我有一个有4个物理核的CPU,每个物理核有两个逻辑核

我的系统有足够的内存来容纳4个并行的
foo
,但不能容纳8个。此外,由于这8个核中有4个是逻辑核,因此我也不希望使用全部8个核将带来比仅使用4个物理核更多的收益

所以我只想在4个物理内核上运行
foo
。换句话说,我想确保执行
多处理.Pool(4)
(4是由于内存限制,我在这台机器上可以容纳的函数的最大并发运行次数)将作业分派给四个物理核(而不是,例如,两个物理核及其两个逻辑子核的组合)

如何在python中实现这一点

编辑:
我之前使用了
多处理
中的一个代码示例,但我不知道库,因此为了避免混淆,我删除了该示例。

注意:此方法在windows上不起作用,仅在linux上测试

使用
多处理。处理

使用
process()
时,为每个进程分配一个物理核心非常容易。您可以使用
taskset-p[mask][pid]
创建一个for循环,循环遍历每个核心,并将新进程分配给新核心:

import multiprocessing
import os

def foo():
    return

if __name__ == "__main__" :
    for process_idx in range(multiprocessing.cpu_count()):
        p = multiprocessing.Process(target=foo)
        os.system("taskset -p -c %d %d" % (process_idx % multiprocessing.cpu_count(), os.getpid()))
        p.start()
我的工作站上有32个内核,因此我将把部分结果放在这里:

pid 520811's current affinity list: 0-31
pid 520811's new affinity list: 0
pid 520811's current affinity list: 0
pid 520811's new affinity list: 1
pid 520811's current affinity list: 1
pid 520811's new affinity list: 2
pid 520811's current affinity list: 2
pid 520811's new affinity list: 3
pid 520811's current affinity list: 3
pid 520811's new affinity list: 4
pid 520811's current affinity list: 4
pid 520811's new affinity list: 5
...
正如您所看到的,这里每个进程的上一个和新的关联。第一个进程用于所有核心(0-31),然后分配给核心0,第二个进程默认分配给核心0,然后将其关联性更改为下一个核心(1),依此类推

使用
多处理.Pool

警告:这种方法需要调整
pool.py
模块,因为据我所知,您无法从
pool()
中提取pid。此外,在
Python2.7
多处理上也对这些更改进行了测试

Pool.py
中,找到调用
\u task\u handler\u start()
方法的行。在下一行中,您可以使用将池中的进程分配给每个“物理”核心(我将
import操作系统
放在这里,以便读者不会忘记导入它):

你完成了。测试:

import multiprocessing

def foo(i):
    return

if __name__ == "__main__" :
    pool = multiprocessing.Pool(multiprocessing.cpu_count())
    pool.map(foo,'iterable here')
结果:

pid 524730's current affinity list: 0-31
pid 524730's new affinity list: 0
pid 524731's current affinity list: 0-31
pid 524731's new affinity list: 1
pid 524732's current affinity list: 0-31
pid 524732's new affinity list: 2
pid 524733's current affinity list: 0-31
pid 524733's new affinity list: 3
pid 524734's current affinity list: 0-31
pid 524734's new affinity list: 4
pid 524735's current affinity list: 0-31
pid 524735's new affinity list: 5
...
pid 705235's current affinity list: 0-31
pid 705235's new affinity list: 0
pid 705236's current affinity list: 0-31
pid 705236's new affinity list: 2
pid 705237's current affinity list: 0-31
pid 705237's new affinity list: 0
pid 705238's current affinity list: 0-31
pid 705238's new affinity list: 2
pid 705239's current affinity list: 0-31
pid 705239's new affinity list: 0
请注意,对
pool.py
的这一修改会将作业自动分配给核心。因此,如果分配的作业多于cpu核心,那么最终会在同一个核心上有多个作业

编辑:

OP想要的是拥有一个能够在特定内核上启动池的
池()。为此,需要对
多处理
进行更多调整(首先撤消上述更改)

警告:

不要试图复制粘贴函数定义和函数调用。仅复制粘贴应该添加在
self.\u worker\u handler.start()之后的部分(您将在下面看到)。请注意,我的
多处理。\uu版本\uu
告诉我版本是
'0.70a1'
,但只要您只添加需要添加的内容,这并不重要:

多处理
pool.py

cores\u idx=None
参数添加到
\uuu init\uuu()定义中。在我的版本中,添加后的外观如下所示:

def __init__(self, processes=None, initializer=None, initargs=(),
             maxtasksperchild=None,cores_idx=None)
此外,还应在
self.\u worker\u handler.start()之后添加以下代码:

多处理
\uuuu init\uuuu.py

在中的
Pool()
定义中添加一个
cores\u idx=None
参数,以及返回部分中的另一个
Pool()
函数调用。在我的版本中,它看起来像:

def Pool(processes=None, initializer=None, initargs=(), maxtasksperchild=None,cores_idx=None):
    '''
    Returns a process pool object
    '''
    from multiprocessing.pool import Pool
    return Pool(processes, initializer, initargs, maxtasksperchild,cores_idx)
你完成了。以下示例仅在核心0和2上运行5个工作线程池:

import multiprocessing


def foo(i):
    return

if __name__ == "__main__":
    pool = multiprocessing.Pool(processes=5,cores_idx=[0,2])
    pool.map(foo,'iterable here')
结果:

pid 524730's current affinity list: 0-31
pid 524730's new affinity list: 0
pid 524731's current affinity list: 0-31
pid 524731's new affinity list: 1
pid 524732's current affinity list: 0-31
pid 524732's new affinity list: 2
pid 524733's current affinity list: 0-31
pid 524733's new affinity list: 3
pid 524734's current affinity list: 0-31
pid 524734's new affinity list: 4
pid 524735's current affinity list: 0-31
pid 524735's new affinity list: 5
...
pid 705235's current affinity list: 0-31
pid 705235's new affinity list: 0
pid 705236's current affinity list: 0-31
pid 705236's new affinity list: 2
pid 705237's current affinity list: 0-31
pid 705237's new affinity list: 0
pid 705238's current affinity list: 0-31
pid 705238's new affinity list: 2
pid 705239's current affinity list: 0-31
pid 705239's new affinity list: 0

当然,通过删除
cores\u idx
参数,您仍然可以使用
multiprocessing.Poll()的常规功能

我找到了一个解决方案,它不涉及更改python模块的源代码。它使用建议的方法。我们只能检查一下 通过执行以下操作运行该脚本后,物理内核处于活动状态:

lscpu
在bash中,返回:

CPU(s):                8
On-line CPU(s) list:   0,2,4,6
Off-line CPU(s) list:  1,3,5,7
Thread(s) per core:    1
[可以从内部运行上面链接的脚本]。在任何情况下,在运行上述脚本后,请在python中键入以下命令:

import multiprocessing
multiprocessing.cpu_count()

返回4。

我知道这个主题现在已经很老了,但是当在google中键入“multiprocessing logical core”时,它仍然是第一个答案。。。我觉得我必须给出一个额外的答案,因为我可以看到2018年(甚至更晚)的人们可能很容易在这里感到困惑(有些答案确实有点困惑)

我看不到比这里更好的地方来警告读者以上的一些答案,所以很抱歉让这个话题复活了

-->要计算CPU(逻辑/物理)数量,请使用PSUTIL模块

对于4物理核心/8线程i7 For ex,它将返回

import psutil 
psutil.cpu_count(logical = False)
四,

八,

就这么简单

在这里,您不必担心操作系统、平台、硬件本身或其他问题我确信它比多重处理要好得多。cpu_count()有时会产生奇怪的结果,至少从我自己的经验来看是这样

-->要使用N个物理内核(由您选择),请使用YUGI描述的多处理模块

只要数一数你有多少个物理进程,就可以启动一个由4个工人组成的多进程池

或者也可以尝试使用joblib.Parallel()函数

2018年的joblib不是标准的一部分
psutil.cpu_count(logical = True)