2014-11-13 1 views
3

최대 부분 배열을 찾는 표준 방법은 Kadene's algorithm입니다. 입력이 큰 숫자 배열 인 경우 원시 파이썬 구현보다 빠릅니다.카디 네의 알고리즘 최적화하기

import timeit 

setup = ''' 
import random 
import numpy as np 

def max_subarray(A): 
    max_so_far = max_ending_here = 0 
    for x in A: 
     max_ending_here = max(0, max_ending_here + x) 
     max_so_far  = max(max_so_far, max_ending_here) 
    return max_so_far 

B = np.random.randint(-100,100,size=100000) 
''' 

print min(timeit.Timer('max_subarray(B)',setup=setup).repeat(5, 100)) 
+0

당신이 더 나은 무엇을 의미합니까없이 주목할만한 증가? 빨리? 순수 Python 구현보다 확실히 빠를 수 있습니다. Cython으로 최적화하고 순수한 C로 작성하고'ctypes' 또는'Cython'을 통해 그것을 포함시킬 수 있습니다. – cel

+0

@cel 예, 분명치 않다면 미안 해요. 더 나은 => 더 빠릅니다. numpy 배열은 이미 최적화 된 데이터 유형 (예 : 고정 데이터 유형, 연속 배열 등)이므로, 활용할 수있는 내장 된 연산이 있는지 궁금합니다. 나는 Cython 경로를 내가 익숙하지 않은 것으로 생각하지 않았다. – Hooked

+0

간단히 실행하거나 실행 시간을 복잡하게 실행하기를 원하십니까? 간단히 nump에서'cumsum'과'sort'를 수행하는 것은 매우 빠릅니다. :) – Wolph

답변

1
iPython 노트북의 사이 썬과

리틀 시험 (그 중 어떤 timeit는 %%cython 환경 :

원래 버전으로 작동하는 것처럼하지 않기 때문에 :

import numpy as np 

B = np.random.randint(-100,100,size=100000) 

def max_subarray(A): 
    max_so_far = max_ending_here = 0 
    for x in A: 
     max_ending_here = max(0, max_ending_here + x) 
     max_so_far  = max(max_so_far, max_ending_here) 
    return max_so_far 

import time 

measurements = np.zeros(100, dtype='float') 
for i in range(measurements.size): 
    a = time.time() 
    max_subarray(B) 
    measurements[i] = time.time() - a 

print 'non-c:', measurements.min(), measurements.max(), measurements.mean() 

사이 썬 버전 :

%%cython 

import numpy as np 
cimport numpy as np 

B = np.random.randint(-100,100,size=100000) 

DTYPE = np.int 
ctypedef np.int_t DTYPE_t 

cdef DTYPE_t c_max_subarray(np.ndarray A): 
    # Type checking for safety 
    assert A.dtype == DTYPE 

    cdef DTYPE_t max_so_far = 0, max_ending_here = 0, x = 0 
    for x in A: 
     max_ending_here = max(0, max_ending_here + x) 
     max_so_far  = max(max_so_far, max_ending_here) 
    return max_so_far 

import time 

measurements = np.zeros(100, dtype='float') 
for i in range(measurements.size): 
    a = time.time() 
    c_max_subarray(B) 
    measurements[i] = time.time() - a 

print 'Cython:', measurements.min(), measurements.max(), measurements.mean() 

결과 :

,451,515,
  • 사이 썬 : 0.00420188903809 0.00658392906189 0.00474049091339
  • 아닌 C : 0.0485298633575 0.0644249916077 0.0522959709167

확실히 너무 많은 노력 :)

+0

정말로 정적으로'x'를 입력해야합니다. 루프 변수이고 산술에서 발생합니다. 나는 당신이 많은 속도를 얻을 것이라고 확신합니다. – cel

+0

'x'가'int'가 될 때'Cython : 0.0273659229279 0.0550830364227 0.0315420007706'과'FastCython : 0.00628685951233 0.0138258934033 0.00742509126663'을 얻습니다. – cel

+0

@cel Cython에 익숙하지 않은 사람들을 위해 정적으로 무엇을 구체적으로 말합니까? x를 int로 입력 하시겠습니까? Cython에서 – Hooked