我正在处理一些非常大的数组。当然,我正在处理的一个问题是RAM耗尽,但在此之前,我的代码运行速度很慢,因此,即使我有无限的RAM,它仍然会花费太长的时间。我将给出我的一些代码来展示我正在尝试做的事情:
#samplez is a 3 million element 1-D array
#zfit is a 10,000 x 500 2-D array
b = np.arange((len(zfit))
for x in samplez:
a = x-zfit
mask = np.ma.masked_array(a)
mask[a <= 0] = np.ma.masked
index = mask.argmin(axis=1)
# These past 4 lines give me an index array of the smallest positive number
# in x - zift
d = zfit[b,index]
e = zfit[b,index+1]
f = (x-d)/(e-d)
# f is the calculation I am after
if x == samplez[0]:
g = f
index_stack = index
else:
g = np.vstack((g,f))
index_stack = np.vstack((index_stack,index))在进一步的计算中,我需要使用g和index_stack,它们中的每一个都是300万x 10,000个二维数组。这个循环的每次迭代几乎需要1秒,所以总共需要300万秒,这太长了。
有没有什么我可以做的,使这个计算运行得更快?我试着想过没有这个for循环我能做什么,但我能想象的唯一方法是制作300万个zfit副本,这是不可行的。
有没有什么办法可以让我不用把所有东西都放在RAM中来处理这些数组呢?我是一个初学者,我搜索过的所有关于这篇文章的东西要么是无关紧要的,要么是我无法理解的。提前谢谢。
发布于 2013-09-29 15:15:38
知道最小正数永远不会出现在行尾是很好的。
在samplez中有100万个唯一值,但在zfit中,每行最多只能有500个唯一值。整个zfit可以有多达5000万个唯一值。如果能够大大减少“寻找最小正数>each_element_in_samplez”的计算量,则可以大大提高算法的速度。做所有的5e13比较可能是一种过度的杀伤力,仔细的计划将能够摆脱其中的很大一部分。这将在很大程度上取决于您实际的基础数学。
在不知道的情况下,仍然可以做一些小事情。1,没有那么多可能的(e-d),所以可以从循环中删除。2、可以通过map消除循环。这两个小的修复,在我的机器上,导致了大约22%的加速。
def function_map(samplez, zfit):
diff=zfit[:,:-1]-zfit[:,1:]
def _fuc1(x):
a = x-zfit
mask = np.ma.masked_array(a)
mask[a <= 0] = np.ma.masked
index = mask.argmin(axis=1)
d = zfit[:,index]
f = (x-d)/diff[:,index] #constrain: smallest value never at the very end.
return (index, f)
result=map(_fuc1, samplez)
return (np.array([item[1] for item in result]),
np.array([item[0] for item in result]))下一步:可以完全避免masked_array (这应该会带来显著的改进)。samplez也需要排序。
>>> x1=arange(50)
>>> x2=random.random(size=(20, 10))*120
>>> x2=sort(x2, axis=1) #just to make sure the last elements of each col > largest val in x1
>>> x3=x2*1
>>> f1=lambda: function_map2(x1,x3)
>>> f0=lambda: function_map(x1, x2)
>>> def function_map2(samplez, zfit):
_diff=diff(zfit, axis=1)
_zfit=zfit*1
def _fuc1(x):
_zfit[_zfit<x]=(+inf)
index = nanargmin(zfit, axis=1)
d = zfit[:,index]
f = (x-d)/_diff[:,index] #constrain: smallest value never at the very end.
return (index, f)
result=map(_fuc1, samplez)
return (np.array([item[1] for item in result]),
np.array([item[0] for item in result]))
>>> import timeit
>>> t1=timeit.Timer('f1()', 'from __main__ import f1')
>>> t0=timeit.Timer('f0()', 'from __main__ import f0')
>>> t0.timeit(5)
0.09083795547485352
>>> t1.timeit(5)
0.05301499366760254
>>> t0.timeit(50)
0.8838210105895996
>>> t1.timeit(50)
0.5063929557800293
>>> t0.timeit(500)
8.900799036026001
>>> t1.timeit(500)
4.614129018783569所以,这是另一个50%的加速。
避免了masked_array,节省了一些内存。我想不出任何其他方法来减少RAM使用量。可能有必要对samplez进行分块处理。此外,依赖于数据和所需的精度,如果您可以使用float16或float32而不是默认的float64,可以节省大量内存。
https://stackoverflow.com/questions/19073455
复制相似问题