Python多处理:限制使用的核心数

时间:2009-10-15 21:04:34

标签: python multiprocessing

我想知道如何将N个独立任务分配给具有L个核心的机器上的M个处理器,其中L> M.我不想使用所有处理器,因为我仍然希望I / O可用。我试过的解决方案似乎被分发到所有处理器,使系统陷入困境。

我认为多处理模块是可行的方法。

我做数值模拟。我的背景是物理学,而不是计算机科学,所以不幸的是,我经常不完全理解涉及标准任务模型的讨论,如服务器/客户端,生产者/消费者等。

以下是我尝试过的一些简化模型:

假设我有一个运行模拟的函数run_sim(**kwargs)(请参阅下面的内容),以及用于模拟的一长串kwargs,我有一个8核心机器。

from multiprocessing import Pool, Process

#using pool
p = Pool(4)
p.map(run_sim, kwargs)

# using process
number_of_live_jobs=0
all_jobs=[]
sim_index=0
while sim_index < len(kwargs)+1:
   number_of_live_jobs = len([1 for job in all_jobs if job.is_alive()])
   if number_of_live_jobs <= 4:
      p = Process(target=run_sim, args=[], kwargs=kwargs[sim_index])
      print "starting job", kwargs[sim_index]["data_file_name"]
      print "number of live jobs: ", number_of_live_jobs
      p.start()
      p.join()
      all_jobs.append(p)
      sim_index += 1

当我使用“top”然后“1”查看处理器使用情况时,无论如何,所有处理器似乎都会被使用。我错误地解释了“top”的输出并不是不可能的,但是如果run_simulation()是处理器密集型的,那么机器会严重陷入困境。

假设模拟和数据:

# simulation kwargs
numbers_of_steps = range(0,10000000, 1000000)
sigmas = [x for x in range(11)]
kwargs = []
for number_of_steps in numbers_of_steps:
   for sigma in sigmas:
      kwargs.append(
         dict(
            number_of_steps=number_of_steps,
            sigma=sigma,
            # why do I need to cast to int?
            data_file_name="walk_steps=%i_sigma=%i" % (number_of_steps, sigma),
            )
         )

import random, time
random.seed(time.time())

# simulation of random walk
def run_sim(kwargs):
   number_of_steps = kwargs["number_of_steps"]
   sigma = kwargs["sigma"]
   data_file_name = kwargs["data_file_name"]
   data_file = open(data_file_name+".dat", "w")
   current_position = 0
   print "running simulation", data_file_name
   for n in range(int(number_of_steps)+1):
      data_file.write("step number %i   position=%f\n" % (n, current_position))
      random_step = random.gauss(0,sigma)
      current_position += random_step

   data_file.close()

5 个答案:

答案 0 :(得分:2)

您可能需要查看以下包:

http://pypi.python.org/pypi/affinity

这是一个使用sched_setaffinity和sched _getaffinity的包。

缺点是它非常适合Linux。

答案 1 :(得分:2)

如果您使用的是Linux,请在启动程序时使用taskset

通过fork(2)创建的子级继承其父级的CPU关联掩码。关联掩码保留在execve(2)中。

  

使用taskset(1)
  Linux用户手册
  使用taskset(1)

     

NAME          taskset - 检索或设置进程的CPU关联性

     

概要          taskset [options] mask命令[arg] ...          taskset [options] -p [mask] pid

     

说明          taskset用于设置或检索正在运行的CPU亲和性   过程给定其PID或启动一个   新          具有给定CPU亲和力的COMMAND。 CPU亲和力是一种调度程序   将进程“绑定”到a的属性   特定          系统上的CPU集。 Linux调度程序将尊重   给定CPU亲和力和过程   将不会          在任何其他CPU上运行。请注意Linux调度程序   支持自然的CPU亲和力:   调度          尝试将进程保持在同一CPU上尽可能长   表现原因。因此,   迫使          特定的CPU关联仅在某些应用程序中有用。

     

CPU亲和性表示为位掩码,具有最低顺序   对应于第一个的位   合乎逻辑          CPU和最后一个逻辑CPU对应的最高位。   并非所有CPU都可能存在于给定的系统上          但是,掩码可以指定比现有更多的CPU。一个检索   掩码只反映那些位   心病          在系统上物理响应CPU。如果是无效的掩码   给定(即,对应于   没有          当前系统上的有效CPU)返回错误。该   掩模通常在   十六进制。

答案 2 :(得分:2)

在我的双核机器上,进程总数得到尊重,即如果我这样做

p = Pool(1)

然后我只看到在任何给定时间使用的一个CPU。该过程可以自由迁移到不同的处理器,但其他处理器空闲。我没有看到您的所有处理器同时使用的情况,因此我不了解这与您的I / O问题有何关联。当然,如果您的模拟受I / O限制,那么无论核心使用情况如何,您都会看到缓慢的I / O ......

答案 3 :(得分:1)

可能是一个愚蠢的观察,请原谅我对Python的经验不足。

但是你完成的任务的while循环轮询不会睡觉并且一直在消耗一个核心,不是吗?

另一件需要注意的事情是,如果你的任务是I / O绑定的,你应该调整你的并行磁盘数量(?)......如果它们是NFS安装在不同的机器上你可能有M&GT;:L

g'luck!

答案 4 :(得分:1)

您可以尝试使用pypar模块。 我不确定如何使用affinity来使用affinity

设置某个核心的cpu亲和性