2013-09-29 2 views
4

나는 아주 큰 배열을 가지고 일하고있다. 물론 다루고있는 문제는 RAM을 다 써 버리는 것입니다.하지만 그 전에도 코드가 느리게 실행되므로 무한한 RAM이 있더라도 너무 오래 걸릴 수 있습니다. 내가 할 노력하고있어 보여 내 코드의 비트를 줄 것이다 :매우 큰 numpy 배열로 효율성

내가 더 계산에 3million X 만 2 차원 배열은 각각의 g 및 index_stack를 사용해야
#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)) 

. 이 루프의 각 반복에는 거의 1 초가 걸리므로 총 길이는 3 백만 초이므로 길다.

계산이 훨씬 빨라질 수있는 방법이 있습니까? 나는 이것을 for 루프없이 어떻게 할 수 있을지 생각하려고 노력했지만, 내가 상상할 수있는 유일한 방법은 zfit의 3 백만 카피를 만드는 것이다. 이것은 실현 불가능하다.

그리고 어딘가에 RAM에 모든 것을 보관하지 않아도이 어레이로 작업 할 수 있습니까? 나는 초급자이고 내가 찾은 모든 것은 부적절하거나 이해할 수없는 것입니다. 미리 감사드립니다.

+1

samplez에 중복 값이 ​​있습니까? 아니면 고유 한 값만 포함하고 있습니까? –

+0

그들은 모두 독특하고 증가하는 순서입니다. – cracka31

+0

'e = zfit [b, index + 1]'에 잠재적 인 문제가 있습니다. 가장 작은 양수 값이 배열의 임의의 행에서 마지막 원소라면,'[b, index + 1]'은 (Indexerror)를 일으킬 것이다. 첫 번째 줄은'b = np.arange (len (zfit)) '이어야합니다. –

답변

1

가장 작은 양수가 행 끝에 표시되지 않습니다.

samplez에는 고유 한 값이 1 백만 개가 있지만 zfit에는 최대 500 개의 고유 값만 가질 수 있습니다. zfit 전체에는 5 천만 개의 고유 값이있을 수 있습니다. '가장 작은 양수> 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을 절약합니다. RAM 사용을 줄이기 위해 다른 것을 생각할 수는 없습니다. 부분적으로 samplez을 처리해야 할 수도 있습니다. 또한 많은 양의 RAM을 절약 할 수있는 float64 대신 float16 또는 float32을 사용할 수있는 경우 데이터 및 필요한 정밀도에 의존합니다.

+0

python3에서'map'은 반복자를 반환하므로 두 번째 배열은 항상 비어 있기 때문에'return' 문은 실패합니다. 또한'\ '를 계속 사용하지 마십시오. 반환 값을 괄호로 묶기 만하면됩니다. – Bakuriu

+0

감사합니다. 좋은 점을 찍었습니다. –

+0

안녕하세요. 이 컴퓨터를 실행할 때 동일한 크기의 배열을 사용하고 있습니까? 귀하의 기계가 이것을 처리 할 수 ​​있습니까? – cracka31

관련 문제