python - 是否可以在多个核上运行依赖于前一个任务的程序?

标签 python python-3.x multiprocessing

我有一个非常大的 python 程序,需要几个小时才能完成,在一个核心上运行。

有什么方法可以将其分配给我电脑上的所有 8 个 i7 核心吗?

唯一的问题是任务依赖于之前的计算,例如,这是我的代码的(非常)简化版本:

def code(nums):
    num = 1
    for loop in range(nums):
        num += num * loop
    return num

然后运行 ​​code()

counted = code(100000)

我可以在任务管理器上观察 CPU 的使用量(大约 12%),显示它只使用一个核心

有没有办法让这段代码在多个内核上运行?

注意:我遇到的主要困难是它依赖于之前的结果,因此我无法将代码分成多个部分。

编辑:

我在 Windows 10 上使用 Python3

编辑2:

如果可能的话,如果上面的代码是我的完整代码,您能写出解决方案吗?

最佳答案

Python 中的多处理

CPython 是 Python 解释器最常见的实现,如果不使用 python 的 multiprocessing 模块,则不具备对多处理的 native 支持。这是由于Python内存不是线程安全的,引入了全局解释器锁(GIL),因此即使是threading模块也没有真正实现并行代码。另一方面,multiprocessing 模块启动 Python 解释器的全新实例,并且由于它们不再共享 GIL,因此可以真正跨多个内核并行运行。

因此,如果您希望运行利用多核的 Python 程序,您必须将程序手动分解为子进程,每个子进程都可以在解释器的单独实例上运行。但请务必小心,因为以这种方式利用多个核心的 yield 可能会比跨核心运行所获得的开销更高,但这非常依赖于项目,因此您应该自己检查一下。

来源:

Multicore Python: A tough, worthy, and reachable goal

Multi-Core and Distributed Programming in Python

Multiprocessing vs Threading Python

您的问题的可能解决方案

现在请耐心等待,因为有几个数学步骤,但我确实相信有一种方法可以使您的代码并行化。

首先获取不同 nums 值的输出示例,看看代码的输出是什么:

nums | 1 | 2 | 3 |  4 |   5 |   6 |
-----------------------------------
out  | 1 | 2 | 6 | 24 | 120 | 720 |

现在,由于您的代码已设置,您可以看到 code(nums) = code(nums - 1) + code(nums - 1) * (nums- 1),所以如果我们可以找到一种从 code(nums - 1)code(nums) 的方法,而实际上不需要知道 code(nums - 1)< 的值 然后我们可以并行化代码。

如果我们现在考虑上表中从 code(nums - 1)code(nums) 的差异,我们会得到下表的差异:

nums | 1 | 2 | 3 |  4 |  5 |   6 |
-----------------------------------
diff |   | 1 | 4 | 18 | 96 | 600 |

现在这些差异可能看起来没有形成一种模式,但实际上有一点逻辑上的飞跃,您可以看到 code(nums)code(nums - 1)(nums - 1) * (nums - 1)! (其中 ! 是数学阶乘函数)。因此我们看到您的 code 方法可以等效地写为:

from math import factorial
def code(nums):
    num = 1
    for i in range(1, nums):
        num += i * factorial(i)
    return num

现在我们可以并行化您的代码了。我们将使用带有 8 个进程池的 multiprocessing 模块(以匹配您的 8 个核心),并将所需工作的一部分映射到每个核心上,允许它们计算所需的值,然后计算总计将结果加起来,然后简单地将结果加 1 以计算 num 的初始值。

from math import factorial
from multiprocessing import Pool, freeze_support

NUM_CORES = 8

def foo(lower, upper):
    sum = 0
    for i in range(lower, upper):
        sum += i * factorial(i)
    return sum

def code(nums):
    # Build the list of arguments for the workers so that each gets 1/NUM_CORES of the work.
    a, b = divmod(nums, NUM_CORES)
    arguments = [(1,a)]
    for c in range(2, NUM_CORES):
        arguments.append(((c-1)*a, c*a))
    arguments.append(((NUM_CORES - 1)*a, NUM_CORES*a + b))

    print(arguments)

    with Pool(processes=8) as pool:
        results = pool.starmap(foo, arguments)

    print(1 + sum(results))

if __name__ == '__main__':
    freeze_support()
    code(100)

需要在底部的 __main__ block 中调用 freeze_support ,以便在 code 方法中正确执行多处理。

关于python - 是否可以在多个核上运行依赖于前一个任务的程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45976342/

相关文章:

python - 将列表的子列表拆分为其他子列表

python - 将 Binary 对象数组转换为 Python 3 中的字符串

python-3.x - 在 XGBoost 中应用增量学习进行分类设置时出错(python)

python - 通过 virtualenv 在 Mac 上安装旧版本的 Python

python 多处理日志记录 : QueueHandler with RotatingFileHandler "file being used by another process" error

Python 多处理 EOF

mysqldb 上的 Python 多处理

python - 对 Python 中 time.clock 的行为感到困惑

python - 将列表与列进行匹配并从列中提取匹配值

python : How to fill an array line by line?