首页 > 解决方案 > 如何将多处理用于函数而不是循环?

问题描述

我写了一个包含大约 400 行的函数。该函数在数据帧上执行某种数据科学。当我运行该功能时,大约需要 10 秒。我需要在每次迭代中使用不同的参数运行这个函数 100 次。因此在循环中我调用该函数 100 次,并且每次迭代我输入 4 个不同的参数。总共花了大约15分钟。因此我想使用CPU Parallelization. 如何在 python 中使用多处理来提供并行化并改善运行时?

代码示例:

result = []
for i range(100):
    result.append(searching_algorithm(a[i], b[i], c[i], d[i]))   

标签: pythonwindowsparallel-processingmultiprocessing

解决方案


您没有说 , 和 是什么a类型bc列表d。这些列表中的元素必须能够使用pickle模块进行序列化,因为它们需要传递给将由在不同地址空间中运行的进程执行的函数。为了论证,我们假设它们是至少长度为 100 的整数列表。

您也没有说明您在什么平台下运行(Windows?MacOS?Linux?)。当你用你标记一个问题时,multiprocessing你应该也用平台标记这个问题。您如何组织代码在一定程度上取决于平台。在下面的代码中,我为那些spawn用于创建新进程的平台(即 Windows)选择了最有效的安排。但这在 MacOS 和 Linux 上也很有效,它们默认用于fork创建新进程。您可以研究与创建新流程相关的内容spawnfork含义。最终要提高内存和 CPU 效率,您只希望作为if __name__ == '__main__':块之外的全局变量,这些变量必须是全球的。这就是为什么我要声明一个函数的本地列表。

然后使用concurrent.futures我们拥有的模块:

from concurrent.futures import ProcessPoolExecutor

def searching_algorithm(a, b, c, d):
    ...
    return a * b * c * d

def main():
    # We assume a, b, c and d each have 100 or more elements:
    a = list(range(1, 101))
    b = list(range(2, 102))
    c = list(range(3, 103))
    d = list(range(4, 104))
    # Use all CPU cores:
    with ProcessPoolExecutor() as executor:
        result = list(executor.map(searching_algorithm, a[0:100], b[0:100], c[0:100], d[0:100]))
    print(result[0], result[-1])

# Required for Windows:
if __name__ == '__main__':
    main()

印刷:

24 106110600

要改用该multiprocessing模块:

from multiprocessing import Pool

def searching_algorithm(a, b, c, d):
    ...
    return a * b * c * d

def main():
    # We assume a, b, c and d each have 100 or more elements:
    a = list(range(1, 101))
    b = list(range(2, 102))
    c = list(range(3, 103))
    d = list(range(4, 104))
    # Use all CPU cores:
    with Pool() as pool:
        result = pool.starmap(searching_algorithm, zip(a[0:100], b[0:100], c[0:100], d[0:100]))
    print(result[0], result[-1])

# Required for Windows:
if __name__ == '__main__':
    main()

在这两个编码示例中,如果列表、a和正好包含 100 个元素,则无需对它们进行切片,例如; 只需传递列表本身,例如:bcda[0:100]

        result = list(executor.map(searching_algorithm, a, b, c, d))

推荐阅读