0

我定义了两种计算python平均值的正确方法。如何在Python中同时计算平均值?

def avg_regular(values): 
    total = 0 
    for value in values: 
     total += value 
    return total/len(values) 

def avg_concurrent(values): 
    mean = 0 
    num_of_values = len(values) 
    for value in values: 
     #calculate a small portion of the average for each num and add to the total 
     mean += value/num_of_values 
    return mean 

第一个功能是计算平均值的常规方式,但我写的第二个因为循环的每次运行不依赖于以前的运行。因此理论上可以平行计算平均值。

但是,“平行”(不平行)的时间比普通的要多30%。

我的假设是否正确,值得速度损失? 如果是的话我怎样才能使第二个函数平行运行第二个函数?

如果不是,我哪里出错了?

+0

你是什么意思与异步?在python asyncio做异步IO,但这并不能真正帮助你。你想加快你的计算?看看numpy。如果你想在多核上运行,请查看多处理(python线程不能同时运行python代码)。你的第二个版本会做更多的工作(每次都是一个部门和一个加法),所以我不认为它需要更多时间是非常令人惊讶的。 – syntonym

+0

@syntonym对不起,我的意思是并行不像异步,就像在多个线程中运行一样。我将如何使用多进程呢? – ChrisIkeokwu

+0

第二个比较慢。更多的分裂! – sascha

回答

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 

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

import numpy 
print(numpy.mean(long_list)) 

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

+0

我不确定,但我认为你是对的,Numpy通常不使用多处理。然而,我认为它尽可能使用向量/ SIMD指令,我相信这是速度提高的部分原因。 – Jarak

+0

@Jarak看起来numpy通过BLAS完成了一些计算任务,因此(使用优化版本时)应该使用向量,SIMD,指令级并行性等。另外,可以使用多线程编译BLAS,但我不确定如果一个总和确实使用它。一般来说python比较慢,因为它需要做很多东西(主要是创建python对象),并且简单地使用[numba](http://numba.pydata.org/)或[cython](http:// cython.org/)应该可以大幅提升速度 – syntonym