11

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

我认为多处理模块是要走的路。

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

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

假设我有一个run_sim(**kwargs)运行模拟的函数(见下文),以及一长串用于模拟的 kwarg,并且我有一台 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()
4

5 回答 5

3

如果您在 linux 上,请在启动程序时使用任务集

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

TASKSET(1)
Linux 用户手册
TASKSET(1)

NAME 任务集 - 检索或设置进程的 CPU 亲和性

概要任务集 [选项] 掩码命令 [arg]...任务集 [选项] -p [掩码] pid

描述任务集用于在给定 PID 的情况下设置或检索正在运行的进程的 CPU 亲和性,或启动具有给定 CPU 亲和性的新命令。CPU 亲和性是一种调度程序属性,它将进程“绑定”到系统上的一组给定 CPU。Linux 调度程序将遵循给定的 CPU 亲和性,并且该进程不会在任何其他 CPU 上运行。请注意,Linux 调度程序还支持自然 CPU 亲和性:出于性能原因,调度程序会尝试将进程保持在同一个 CPU 上,只要可行。因此,强制特定的 CPU 亲和性仅在某些应用程序中有用。

CPU 亲和性表示为位掩码,最低位对应于第一个逻辑 CPU,最高位对应于最后一个逻辑 CPU。并非所有 CPU 都可能存在于给定系统上,但掩码可能指定比现有更多的 CPU。检索到的掩码将仅反映与系统上物理 CPU 对应的位。如果给出了无效掩码(即,对应于当前系统上没有有效 CPU 的掩码),则返回错误。掩码通常以十六进制给出。

于 2009-10-15T21:50:24.453 回答
2

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

p = Pool(1)

然后我在任何给定时间都只看到一个 CPU 正在使用中。该进程可以自由迁移到另一个处理器,但随后另一个处理器处于空闲状态。我看不到您的所有处理器如何同时使用,所以我不知道这与您的 I/O 问题有何关系。当然,如果您的模拟受 I/O 限制,那么无论内核使用情况如何,您都会看到 I/O 缓慢...

于 2009-10-15T22:06:38.820 回答
2

您可能需要查看以下软件包:

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

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

缺点是它是高度特定于 Linux 的。

于 2009-10-15T21:16:49.077 回答
1

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

但是您对已完成任务的 while 循环轮询不会进入睡眠状态,并且一直在消耗一个内核,不是吗?

需要注意的另一件事是,如果您的任务受 I/O 限制,则应将 M 调整为您拥有的并行磁盘的数量(?)...如果它们是 NFS 安装在不同的机器上,您可能有 M>L .

祝你好运!

于 2009-10-15T23:50:03.373 回答
1

您可以尝试使用 pypar 模块。我不知道如何使用亲和力来使用亲和力设置某个核心的 cpu 亲和力

于 2011-03-26T18:25:00.913 回答