2010-01-05 2 views
1

저는 파이썬 API가 카산드라와 같은 대형 데이터 저장소를 찾는 방법에 대해 생각하려고합니다. R, Matlab 및 NumPy는 "모든 것이 행렬입니다"공식을 사용하고 각 작업을 개별적으로 실행하는 경향이 있습니다. 이 모델은 메모리에 저장할 수있는 데이터에 효과적이라는 것을 입증했습니다. 그러나 큰 데이터에 대한 SAS의 이점 중 하나는 행별로 실행하여 다음 행으로 이동하기 전에 모든 행 계산을 수행한다는 것입니다. Cassandra와 같은 데이터 저장소의 경우이 모델은 거대한 승리처럼 보입니다. 데이터를 한 번만 반복합니다. 명시 적으로 이것은파이썬에서 큰 데이터를 지연 실행했습니다.

with load('datastore') as data: 
    for row in rows(data): 
    row.logincome = row.log(income) 
    row.rich = "Rich" if row.income > 100000 else "Poor" 

하지만 한 번만 반복의 장점이있다 (도?) :

파이썬에서, SAS의 접근 방식은 같은 것을 볼 수 있습니다. 더 작은 데이터 세트의 경우, 함수가 컴파일 된 코드를 사용하여 벡터화되지 않기 때문에 성능이 NumPy에 비해 매우 열악합니다. R/NumPy와에서 우리는 훨씬 더 간결하고 컴파일을 할 것이다 : logifelse 그 벡터에 연산자를 모두 컴파일 된 함수이기 때문에

data.logincome = log(data.income) 
data.rich = ifelse(data.income > 100000, "Rich", Poor") 

이 매우 빠르게 실행됩니다. 그러나 단점은 두 번 반복된다는 것입니다. 작은 데이터 세트의 경우 이것은 중요하지 않지만 Cassandra 백업 데이터 저장소의 경우이 접근 방식이 어떻게 작동 하는지를 볼 수 없습니다.

질문 : 두 번째 API (예 : R/Numpy/Matlab)를 유지하는 방법이 있지만 계산 지연이 있습니다. 마지막에 sync (data) 함수를 호출하면 될까요?

다른 아이디어? NumPy 형식 구문을 유지하는 것이 좋을 것입니다. 사용자가 작은 작업에 NumPy를 사용하고 어떻게 작동하는지 직관적으로 파악할 수 있기 때문입니다.

답변

2

저는 Cassandra/NumPy에 대해 아무것도 몰라요. 그러나 NumPy를 사용하는 두 번째 방법을 적당한 크기의 청크로 처리하면 CPU 및 파일 시스템 캐시의 이점을 누릴 수 있습니다. 최적화 된 처리 기능 사용의 이점을 포기하지 않고 데이터를 두 번 반복함으로써 발생하는 모든 속도 저하.

1

나는 완벽한 대답을하지는 못했지만 어쨌든 그것은 가치가 있습니다. 그것은 파이썬 생성기를 중심으로 일종의 생산자 - 소비자 스타일 조합입니다. 이제

for row in rows(data): 
    # do stuff with row 

에 열을 공급 (임의의 : 두 번 루프를 원하지 않기 때문에, 나는이 같은 행에 대한 명시 적 루프 주위에 방법이 없다 생각 하나

, 다시 말해, 발전기를 다시는 초크 화하지 마십시오. 그러나 당신은 발전기의 send 방법을 사용할 것입니다.

def riches(): 
    rich_data = [] 
    while True: 
     row = (yield) 
     if row == None: break 
     rich_data.append("Rich" if row.income > 100000 else "Poor") 
    yield rich_data 

제 수율 (식)에 불과하다 riches 개별 행 연료 : 이러한 소비자 예로서, 여기 riches의 스케치이다. 그것은 결과 배열을 만드는 일을합니다. while 루프 후에 두 번째 yield (statement)는 결과 데이터를 실제로 호출자에게 제공하는 데 사용됩니다.

호출자 루프로 돌아가서,이 같은가 someting을 볼 수 있었다 :

richConsumer = riches() 
richConsumer.next() # advance to first yield 
for row in rows(data): 
    richConsumer.send(row) 
    # other consumers.send(row) here 
richConsumer.send(None) # make consumer exit its inner loop 
data.rich = richConsumer.next() # collect result data 

을 내가 그 코드를 테스트하지 않은,하지만 난 그것에 대해 어떻게 생각하는지 그건. 벡터 기반 함수의 멋진 압축 구문을 가지고 있지 않습니다. 그러나 메인 루프를 매우 단순하게 만들고 모든 처리를 별도의 소비자로 캡슐화합니다.추가 소비자는 서로 잘 쌓일 수 있습니다. 그리고 API는 발전기 관리 코드를 뒤로 밀면 더욱 연마 될 수 있습니다. 객체 경계. HTH

+0

나는 당신이하고있는 일을 완전히 잘하고 있는지 잘 모르겠습니다. 행이 기본 데이터에 대한 뷰인 행을 반복하는 첫 번째 옵션보다 어떻게 개선 될까요? – Tristan

+0

음, 최상위 루프가 필요하다는 것을 확인합니다. 또 다른 한가지로, 여러분의 우려 중 하나는 루프 몸체와 별도의 함수에서 코드를 처리하는 것이라고 생각했습니다. (여러분은 "컴파일 된 함수"의 이점에 대해 이야기했는데, 이것이 파이썬에서 얼마나 많은 의미가 있는지 모르겠지만, 이러한 함수를 나중에 C 코드로 푸시 할 생각이라면 많은 의미가 있습니다). 세 번째 관심사는 처리 기능을위한 깔끔한 API였습니다. 이러한 제약 조건을 감안할 때 나는이 생산자 - 소비자 접근법이 좋은 타협이라고 생각했다. 그러나 YMMV. – ThomasH

관련 문제