Python 改进等距列表上的sum()计算
我有一个代码,其中需要1000万个0到1之间的等距数字,我有一个逻辑函数,负责选择一个随机索引,并返回从该索引到列表末尾的数字总和 因此代码如下所示Python 改进等距列表上的sum()计算,python,numpy,Python,Numpy,我有一个代码,其中需要1000万个0到1之间的等距数字,我有一个逻辑函数,负责选择一个随机索引,并返回从该索引到列表末尾的数字总和 因此代码如下所示 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 ran
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 loopsum(),每个结果大约需要1.3秒
有没有有效的方法来减少每次调用1.3秒的等待时间?我也尝试过创建一种缓存字典,但是deep\u dive\u 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))
我需要有关缓存1000万字典或替代公式的帮助,以便在不使用sum()或任何现成解决方案的情况下返回结果。
np.sum(一千万)
大约在0.005秒内完成,而sum(一千万)
在我的机器上大约是1.5秒
至于不使用任何现成函数的解决方案,正如MrT对您的问题的评论中所建议的,您可以使用算术级数的属性,即级数的和等于n(a1+an)/2
,其中n
是元素数(10000000),a1是第一个元素(0),an是最后一个元素(1)。在您的示例中,这是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
此外,它的运算速度也非常快,事实上,比np.sum
快得多:在我的机器上,算术级数计算平均耗时1.223e-06秒,而np.sum
则耗时0.00577秒。有道理,看看它是怎样的一个加法,一个乘法,一个除法…np.sum(一千万)
大约在0.005秒内完成,而sum(一千万)
在我的机器上大约是1.5秒
至于不使用任何现成函数的解决方案,正如MrT对您的问题的评论中所建议的,您可以使用算术级数的属性,即级数的和等于n(a1+an)/2
,其中n
是元素数(10000000),a1是第一个元素(0),an是最后一个元素(1)。在您的示例中,这是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
此外,它的运算速度也非常快,事实上,比np.sum
快得多:在我的机器上,算术级数计算平均耗时1.223e-06秒,而np.sum
则耗时0.00577秒。有道理,看看它只是一个加法、一个乘法和一个除法…分析一下:
def cumm_sum(start, finish, steps, k):
step = (finish - start) / steps
pop = (finish - k) / step
return (pop + 1) * 0.5 * (k + finish)
电话是这样的:
pick = ten_million[random.randint(0, 10000000)]
result = cumm_sum(0.0, 1.0, 10000000, pick)
进行分析:
def cumm_sum(start, finish, steps, k):
step = (finish - start) / steps
pop = (finish - k) / step
return (pop + 1) * 0.5 * (k + finish)
电话是这样的:
pick = ten_million[random.randint(0, 10000000)]
result = cumm_sum(0.0, 1.0, 10000000, pick)
(m+n)*(m-n+1)*0.5
ten_m = 10000000
def sum10m_py(n):
return (1+n)*(ten_m-n*ten_m+1)*0.5
sum_np = np.vectorize(sum_py)
mask = np.random.randint(0,ten_m,2500)
sums = sum_np(ten_million[mask])
(m+n)*(m-n+1)*0.5
ten_m = 10000000
def sum10m_py(n):
return (1+n)*(ten_m-n*ten_m+1)*0.5
sum_np = np.vectorize(sum_py)
mask = np.random.randint(0,ten_m,2500)
sums = sum_np(ten_million[mask])
您是否尝试过
numpy.sum
?它可能更快。是的,使用numpy.sum
,在我的机器上,时间从1.5秒左右变为0.015秒。你可以解析地解决这个问题。我不理解你的问题,如果它们是等距分布的,它们是求和的显式公式。你有第一个、最后一个和元素数。您不需要其他任何东西来计算总和。您是否尝试过numpy.sum
?它可能更快。是的,使用numpy.sum
,在我的机器上,时间从1.5秒左右变为0.015秒。你可以解析地解决这个问题。我不理解你的问题,如果它们是等距分布的,它们是求和的显式公式。你有第一个、最后一个和元素数。您不需要任何其他内容来计算总和。我不确定这是否会返回有效答案cumm_sum(0.0,1.0,10000000,千万[5000])=4999999.250249749
,但是sum(千万[5000:])=4999998.750249899
step
引入了不必要的浮点错误。打印出pop
查看我的意思。我不确定这是否返回有效答案cumm_sum(0.0,1.0,10000000,千万[5000])=499999.250249749
但是sum(千万[5000:])=4999998.750249899
步骤引入了不必要的浮点错误。打印出pop
以查看我的意思。这不应该是((一千万)挑选)*(一千万[pick]+一千万[-1])/2
?因为n是我们要添加的元素数..这不是((len(一千万)-pick)*(一千万[pick]+一千万[-1])/2
?因为n是我们要添加的元素数。这返回sum_np(千万[5000]]=2.4987505e+17
但是sum(千万[5000]=4999998.750249899
谢谢,修复了函数sum10m_py
中的错误。这返回sum_np(千万[5000]]=2.4987505e+17
(千万[5000:])=4999998.750249899谢谢,修复了函数sum10m_py