如何在python中同时计算平均值?

时间:2017-02-19 17:09:19

标签: python python-3.x concurrency multiprocessing python-multiprocessing

我在python中定义了两种计算平均值的正确方法。

@RequestMapping(value = "/getUserScoreCardDetails", method = RequestMethod.GET)
public @ResponseBody List<ScoreDetails> getUserScoreCardDetails(
@RequestParam(value = "playerIds", required = false, defaultValue="1,2,3") int[] playerIds) { 

}

第一个函数是计算平均值的常规方法,但是我写了第二个函数,因为循环的每次运行都不依赖于先前的运行。因此理论上平均值可以并行计算。

然而,“并行”(没有并行运行)比常规时间多30%。

我的假设是否正确且值得减速? 如果是,我怎么能让第二个函数并行运行第二个函数?

如果没有,我哪里出错?

1 个答案:

答案 0 :(得分:1)

您实施的代码基本上是(a1+a2+ ... + an) / n(a1/n + a2/n + ... + an/n)之间的差异。结果是相同的,但在第二个版本中有更多的操作(即(n-1)个更多的划分),这减慢了计算速度。您声称在第二个版本中,每个循环运行独立于其他循环。在第一个循环中,我们需要以下信息来完成一个循环运行:运行前的total和当前的value。在第二个版本中,我们需要以下信息来完成一次循环运行:运行前mean,当前valuenum_of_values。正如您在第二个版本中看到的,我们甚至依赖更多的值!

但是我们如何划分核心之间的工作(这是多处理的目标)?我们可以给出一个核心的前半部分值,第二个核心给出后半部分,即((a1+a2+ ... + a(n//2)) + ( a(n//2 +1) + ... + a(n)) / n)。是的,除以n的工作不是在核心之间分开,而是它是一条指令,所以我们并不关心。此外,我们还需要添加左侧总计和右侧总计,这是我们无法拆分的,但同样只需要一次操作。

所以我们要运行的代码:

def my_sum(values):
    total = 0
    for value in values:
        total += value
    return total

python仍然存在问题 - 通常可以使用线程进行计算,因为每个线程将使用一个核心。但是在这种情况下,必须注意你的程序不会遇到竞争条件,而python解释器本身也需要处理这个问题。 CPython认为它不值得,基本上一次只能在一个线程中运行。基本解决方案是通过多处理使用多个流程。

from multiprocessing import Pool

if __name__ == '__main__':

    with Pool(5) as p:
        results = p.map(my_sum, [long_list[0:len(long_list)//2], long_list[len(long_list)//2:]))

    print(sum(results) / len(long_list)) # add subresults and divide by n

但当然多个过程不是免费的。你需要分叉,复制东西等,所以你不会像人们预期的那样获得2的加速。最大的减速实际上是使用python本身,它并没有真正优化快速数值计算。有各种各样的方法,但使用numpy可能是最简单的。只需使用:

import numpy
print(numpy.mean(long_list))

这可能比python版本快得多。我不认为numpy使用内部多处理,因此可以通过使用多个进程和快速实现(numpy或其他用C编写的东西)来获得提升,但通常numpy足够快。