我有python函数,它们应该在使用多核的linux环境中并行运行。有没有办法明确指定每个流程应该使用哪个核心?
目前,我正在使用python多处理模块在4个核心中作为并行进程运行这些python函数。
import multiprocessing as mp
def hello(name, msg):
try:
print("Hello {}".format(name))
print(msg)
return true
except Exception:
return False
pool = mp.Pool(mp.cpu_count())
msg = "It's a holiday!"
name_list = ["A", "B", "C"]
hello_status = pool.starmap(hello,[(name, msg) for name in name_list])
print(hello_status)
可能是os.sched_setaffinity
和os.sched_getaffinity
的组合。文档字符串显示:
签名:os.sched_setaffinity(pid,mask,/)
文档字符串:
将pid标识的进程的CPU相关性设置为掩码。
掩码应该是标识CPU的整数的可迭代。
类型:内置函数或方法
我找不到Python特定的文档,但这些手册页应该是很好的第一个信息来源。
更新:
我决定研究multiprocessing
模块,并编写一个工作示例。我用multiprocessing.Pool
类想出了两种方法。第一种方法是将initializer
参数传递给Pool
构造函数调用。第二种是使用Pool.map
函数。
import os
from itertools import cycle
import multiprocessing as mp
def _myinit():
my_pid = os.getpid()
old_aff = os.sched_getaffinity(0)
os.sched_setaffinity(0, [0, 3])
new_aff = os.sched_getaffinity(0)
print("My pid is {} and my old aff was {}, my new aff is {}".format(my_pid, old_aff, new_aff))
def map_hack(AFF):
my_pid = os.getpid()
old_aff = os.sched_getaffinity(0)
os.sched_setaffinity(0, AFF)
return (my_pid, old_aff, os.sched_getaffinity(0))
PROCESSES = os.cpu_count()
# just an example iterable you could use for the map_hack
# elements of cpus must be iterables, because of os.sched_setaffinity
_mycpus = cycle(os.sched_getaffinity(0))
cpus = [[next(_mycpus)] for x in range(PROCESSES)]
# Since Python 3.3 context managers are supported for mp.Pool
# using initializer argument to change affinity
with mp.Pool(processes=PROCESSES, initializer=_myinit) as pool:
# do something conditional on your affinity
pool.close()
pool.join()
print("")
# using mp.Pool.map hack to change affinity
with mp.Pool(processes=PROCESSES) as pool:
for x in pool.map(map_hack, cpus, chunksize=1):
print("My pid is {} and my old aff was {}, my new aff is {}".format(*x))
# do something conditional on your affinity
pool.close()
pool.join()
注意,使用initializer
,我对第一个和第四个CPU(0,3)的所有进程的亲和性进行了硬编码,但这只是因为我发现像使用map_hack
那样使用cycle
有点困难。我还想证明,您可以为任何(合法)数量的cpu设置亲和性。
我建议你仔细阅读代码,并确保通过阅读相关文档和更改一些参数来理解它。不用说,所有的print
声明都只是为了让我们相信这些方法是有效的。
最后,如果您想要更多的控制,我建议您使用mp.Process
对象,而不是mp.Pool
。os
中的相同工具也应该派上用场。
WINDOWS:
如果您使用的是Windows,这将不起作用。来自文档:
这些函数控制操作系统如何分配进程的CPU时间。它们仅在某些Unix平台上可用。有关更多详细信息,请参阅Unix手册页。
在这种情况下,您可以查看win32process
,特别是win32process.SetProcessAffinityMask
和win32process.GetProcessAffinityMask
,请参阅此处。