【问题标题】:From multiprocessing to distributed processing in python standard librarypython标准库中从多处理到分布式处理
【发布时间】:2014-10-22 20:52:21
【问题描述】:

我正在研究来自gitHub 的关于分布式处理的code。我要感谢 eliben 提供的这个好 post。我已经阅读了他的解释,但有一些黑点。据我了解,该代码用于在多台机器/客户端中分配任务。我的问题是:

  1. 我最基本的问题是工作分配到不同机器的位置是什么?

  2. 为什么 main 函数中有 if else 语句?

  3. 让我以更笼统的方式开始这个问题。我认为我们通常在特定的块(独立内存部分)中启动Process,而不是像这样一次传递所有块:

    chunksize = int(math.ceil(len(HugeList) / float(nprocs)))
    for i in range(nprocs):
    p = Process(
                target = myWorker, # This is my worker
                args=(HugeList[chunksize * i:chunksize * (i + 1)],
                HUGEQ)      
    processes.append(p)
    p.start() 
    

    在这个简单的例子中,我们有nprocs 进程。每个进程都会启动函数myWorker 的一个实例,该实例作用于指定的块。

    我的问题是:

    • 对于在每个块中工作的每个进程,我们有多少线程?
  4. 现在查看gitHub 代码我想了解mp_factorizer?更具体地说,在这个函数中,我们没有块,而是一个巨大的队列 (shared_job_q)。这个巨大的队列由最大大小为 43 的子列表组成。这个队列被传递到factorizer_worker。我们通过get 获取这些子列表并将它们传递给串行工作者。我知道我们需要这个队列来在客户端之间共享数据。

    我的问题是:

    • 我们是否为每个nprocs(=8) 进程调用factorizer_worker 函数的实例?
    • 每个进程工作的数据的哪一部分? (一般情况下,我们有 8 个进程和 43 个块。)
    • 每个进程有多少个线程?
    • 是否从每个进程线程调用get 函数?

感谢您的宝贵时间。

【问题讨论】:

    标签: python multithreading multiprocessing distributed parallel-python


    【解决方案1】:

    仅当您实际在多台机器上运行脚本时才会分发到多台机器。第一次运行脚本(不带 --client 选项)时,它会在特定 IP/端口上启动 Manager 服务器,该 IP/端口托管共享作业/结果队列。除了启动 Manager 服务器之外,runserver 还将通过调用 mp_factorizer 来充当 worker。它还负责从结果队列中收集结果并进行处理。您可以自行运行此脚本并获得完整的结果。

    但是,您也可以通过使用 --client 选项在其他机器上运行脚本来将分解工作分发到其他机器。这将调用 runclient,它将连接到您在初始运行脚本时启动的现有 Manager 服务器。这意味着客户端正在访问 runserver 正在使用的相同共享队列,因此它们都可以从相同的队列中提取工作并将结果放入相同的队列中。

    以上内容应涵盖问题 1 和 2。

    我不确定您在问题 3 中要问什么。我认为您想知道为什么我们不将列表的一部分明确地传递给每个工人(就像在您包含的示例),而不是将所有块放入队列中。答案是因为runserver 方法不知道实际会有多少工人。它知道它将启动 8 个工人。但是,它不想将HugeList 拆分为八个块并将它们发送到它正在创建的 8 个进程,因为它也希望支持远程客户端连接到Manager 并进行工作。因此,它为每个块 (43) 选择任意大小,并将列表划分为消耗整个 HugeList 所需的尽可能多的块,并将其粘贴在 Queue 中。这是runserver 中的代码:

    chunksize = 43
    for i in range(0, len(nums), chunksize):
        #print 'putting chunk %s:%s in job Q' % (i, i + chunksize)
        shared_job_q.put(nums[i:i + chunksize]) # Adds a 43-item chunk to the shared queue.
    

    这样,任意数量的工作人员都可以连接到Manager 服务器,从shared_job_q 获取一个块,对其进行处理,然后返回一个结果。

    我们是否为每个 nprocs(=8) 进程调用 factorizer_worker 函数的实例?

    是的

    每个流程工作的数据的哪一部分? (一般情况下,我们有 8 个进程和 43 个块。)

    我们没有 43 个块。我们有 X 个块,每个大小为 43。每个工作进程只是从队列中抓取块并处理它们。它得到哪一部分是任意的,取决于有多少工人以及每个工人的速度。

    每个进程有多少个线程?

    一个。如果您的意思是现在每个脚本实例都存在许多工作进程,那么服务器进程中有 8 个,每个客户端进程中有 4 个。

    是否从每个进程线程调用 get 函数?

    不知道你的意思。

    【讨论】:

    • 感谢我正在努力的答案。给我一些时间来处理你的逻辑。 :)
    • 所以在mp_factorizer 中我们启动nprocs 进程。每个进程都掌握shared_job_q 队列,并在factorizer_worker 中处理它。从现在开始,我了解到一个进程对应于一个在单独的内存部分(块)上工作的线程。因此,每个线程都会获得 (get_nowait) 一个子列表并使用 outdict = {n: factorize_naive(n) for n in job} 行。服务器上的 8 个线程(进程)几乎同时发生这种情况。所有线程进程都由get_nowait() 同步。您能否对我的逻辑进行更正?谢谢!
    • @Thoth 是的,这一切都正确,假设您将“线程”这个词换成“进程”。这里没有多线程,都是多处理。
    • 不错!所以最后一个问题Does get function called from each process thread? 现在对你或我来说都更清楚了。 :)。 get 函数 (get_nowait) 每次都由单个进程/线程调用。我认为现在执行对我来说更清楚了,多亏了你,基础知识得到了澄清,还有更多的研究需要同化:)!!!
    猜你喜欢
    • 1970-01-01
    • 2016-07-10
    • 1970-01-01
    • 2015-01-08
    • 2010-10-02
    • 1970-01-01
    • 2019-01-30
    • 1970-01-01
    • 2022-01-10
    相关资源
    最近更新 更多