改进均匀间隔列表上的sum()计算

时间:2018-02-22 13:59:47

标签: python numpy

我有一个代码,我需要在0和1之间的10Million均匀间隔数字,我有一个逻辑函数,负责选择一个随机索引,返回该索引的数字总和,直到列表的末尾即可。

因此代码如下所示,

import random
import numpy as np

ten_million = np.linspace(0.0, 1.0, 10000000)

def deep_dive_logic():
    # this pick is derived from good logic, however, let's just use random here for demonstration
    pick = random.randint(0, 10000000)
    return sum(ten_million[pick:])

for _ in range(2500):
  r = deep_dive_logic()
  print(r)

  # more logic ahead...

这里的问题是 I循环 sum()在这样的大小列表上需要大约。每个结果1.3秒。

enter image description here

有没有有效的方法来减少每次调用的1.3s等待?我也尝试创建一种缓存字典,但是deep_dive_logic()函数在多进程环境中运行,因此有需要缓存这个字典,redis或json.dump不是一个选择,因为字典安装的大小大约为236MB,如果没有缓存,则会增加进程间通信的开销。

sums_dict = {0: sum(ten_million)}
even_difference = (ten_million[1] - ten_million[0])

for i in range(len(ten_million) - 1):
    sums_dict[i+1] = sums_dict[i] - (even_difference * (i+1))

我需要帮助缓存10万字典或替代公式,以便在不使用sum()或任何现成解决方案的情况下返回结果。

https://repl.it/repls/HoneydewGoldenShockwave

3 个答案:

答案 0 :(得分:3)

np.sum(ten_million)在约0.005秒内完成,而sum(ten_million)在我的机器上约为1.5秒

对于没有使用任何现成功能的解决方案,正如MrT对你的问题的评论中所建议的那样,你可以使用算术进展的属性,它表示进展的总和等于{{1其中n(a1+an) / 2是元素的数量(10000000),a1是你的第一个元素(0),a是你的最后一个元素(1)。在您的示例中,这是n

所以,对于你的deep_dive_logic函数,只需返回:

10000000(0+1) / 2 = 5000000

这项工作也非常快,实际上比def deep_dive_logic(): pick = random.randint(0, 10000000) return (len(ten_million)-pick)*(ten_million[pick]+ten_million[-1]) / 2 快得多:平均而言,算术级数计算需要1.223e-06秒,而np.sum在我的机器上需要0.00577秒。有道理,看看它只是一个加法,一个乘法和一个除法......

答案 1 :(得分:1)

分析地做:

abstract type ABS{A,B} end
struct Myk <: ABS{Int64,Float64} end

struct MyStruct{A,B,K<:ABS{A,B}}
    a::A
    b::B
    MyStruct{A,B,K}(a::A,b::B) where {A,B,K<:ABS{A,B}}= new(a,b)
end
# this is the outer constructor:
MyStruct(a::A, b::B, ::K) where {A,B,K<:ABS{A,B}} = MyStruct{A,B,K}(a,b)

# now this works:
MyStruct(1,2.1,Myk())

并且电话会像:

def cumm_sum(start, finish, steps, k):
    step = (finish - start) / steps
    pop = (finish - k) / step
    return (pop + 1) * 0.5 * (k + finish)

答案 2 :(得分:0)

  1. 使用数学来减少问题的复杂性:

    算术级数的总和由

    给出
    (m+n)*(m-n+1)*0.5
    
  2. 使用np.vectorize加速数组操作:

    ten_m = 10000000
    
    def sum10m_py(n):
        return (1+n)*(ten_m-n*ten_m+1)*0.5
    
    sum_np = np.vectorize(sum_py)
    
  3. 选择所需的元素,然后在其上应用矢量化函数。

    mask = np.random.randint(0,ten_m,2500)
    
    sums = sum_np(ten_million[mask])