首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >非常大的numpy数组的效率

非常大的numpy数组的效率
EN

Stack Overflow用户
提问于 2013-09-29 09:15:18
回答 1查看 2K关注 0票数 4

我正在处理一些非常大的数组。当然,我正在处理的一个问题是RAM耗尽,但在此之前,我的代码运行速度很慢,因此,即使我有无限的RAM,它仍然会花费太长的时间。我将给出我的一些代码来展示我正在尝试做的事情:

代码语言:javascript
复制
#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中来处理这些数组呢?我是一个初学者,我搜索过的所有关于这篇文章的东西要么是无关紧要的,要么是我无法理解的。提前谢谢。

EN

回答 1

Stack Overflow用户

发布于 2013-09-29 15:15:38

知道最小正数永远不会出现在行尾是很好的。

samplez中有100万个唯一值,但在zfit中,每行最多只能有500个唯一值。整个zfit可以有多达5000万个唯一值。如果能够大大减少“寻找最小正数>each_element_in_samplez”的计算量,则可以大大提高算法的速度。做所有的5e13比较可能是一种过度的杀伤力,仔细的计划将能够摆脱其中的很大一部分。这将在很大程度上取决于您实际的基础数学。

在不知道的情况下,仍然可以做一些小事情。1,没有那么多可能的(e-d),所以可以从循环中删除。2、可以通过map消除循环。这两个小的修复,在我的机器上,导致了大约22%的加速。

代码语言:javascript
复制
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也需要排序。

代码语言:javascript
复制
>>> 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进行分块处理。此外,依赖于数据和所需的精度,如果您可以使用float16float32而不是默认的float64,可以节省大量内存。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19073455

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档