如何使用并行计算编写列表的函数



我正在尝试使用并行计算编写一个python函数,以快速计算列表的总和。最初,我尝试使用Python多线程库,但是后来我注意到所有线程都在同一CPU上运行,因此没有速度增益,因此我切换到使用多处理。在第一个版本中,我使列表成为一个全局变量:

from multiprocessing import Pool
array = 100000000*[1]
def sumPart(fromTo:tuple):
    return sum(array[fromTo[0]:fromTo[1]])
with Pool(2) as pool:
    print(sum(pool.map(sumPart, [(0,len(array)//2), (len(array)//2,len(array))])))

这效果很好,并在串行计算的一半时间后返回了正确的总和。

,但后来我想使其成为一个接受数组作为参数的函数:

def parallelSum(theArray):
    def sumPartLocal(fromTo: tuple):
        return sum(theArray[fromTo[0]:fromTo[1]])
    with Pool(2) as pool:
        return (sum(pool.map(sumPartLocal, [(0, len(theArray) // 2), (len(theArray) // 2, len(theArray))])))

在这里我有一个错误:

AttributeError: Can't pickle local object 'parallelSum.<locals>.sumPartLocal'

编写此功能的正确方法是什么?

在将作业安排到python Pool时,您需要确保函数和参数可以序列化,因为它们将通过pipe传输。

Python使用pickle协议来序列化其对象。您可以在模块文档中查看可以腌制的内容。就您而言,您正在面临此限制。

在模块的最高级别定义的功能(使用def,而不是lambda)

在引擎盖下,Pool正在发送带有函数名称及其参数的字符串。儿童过程中的python解释器在模块中寻找该函数名称,并且在嵌套在另一个函数 parallelSum的范围中时未能找到它。

移动sumPartLocalparallelSum外部,一切都可以。

我相信您正在击中它,或者查看文档

您可以做的是在模块级别离开def sumPartLocal,然后将theArray作为tuple的第三个组件,因此在sumPartLocal函数中是fromTo[2]

示例:

from multiprocessing import Pool
def sumPartLocal(fromTo: tuple):
    return sum(fromTo[2][fromTo[0]:fromTo[1]]) 
def parallelSum(theArray):
    with Pool(2) as pool:
        return (sum
                (pool.map
                 (sumPartLocal, [
                     (0, len(theArray) // 2, theArray), 
                     (len(theArray) // 2, len(theArray), theArray)
                     ]
                  )
                 )
                )
if __name__ == '__main__':
    theArray = 100000000*[1]
    s = parallelSum(theArray)
    print(s)

[基于评论的编辑15-Dec-2017]

任何想在Python中考虑多线程的人,我强烈建议您阅读有关全球口译锁的信息

另外,在此问题上,关于

的这个问题有一些很好的答案

相关内容

  • 没有找到相关文章

最新更新