2014-10-15 6 views
0

비교적 간단하게 병렬화 할 수있는 문제가 있는데, 이로 인해 효과적으로 구현하기에는 너무 많은 문제가 발생합니다. 내 프로그램의 핵심에는 두 개의 행렬과 두 개의 벡터, 즉 수행하려는 두 가지 계산 각각에 대한 행렬과 벡터가 있습니다.파이썬 다중 처리에서 전역 변수 .Pool 클래스

나는 각 벡터의 매우 큰 목록을 가지고 :

는 코드에서 그게 내가 내가 원하는 무엇

import numpy as np 
matrices = dict([("type1", np.random.rand(10,10)), ("type2", np.random.rand(10,10))]) 
vectors = dict([("type1", np.random.rand(10)), ("type2", np.random.rand(10))]) 

이 (정말 아니지만, 단순화 된 경우)이 의미 유형 :

input_vectors = [np.random.rand(10) for i in range(1000)] 

내가 A 행렬과 b 각 유형의 벡터이다 A*v+b을 계산합니다.

내가 필요한 것을 수행하는 단일 스레드 코드는 그러나, 나는이 병렬로이 작업을 수행 할 수 있으므로

def f(input_vector, matricx, vector): 
    return np.dot(matrix, input_vector) + vector 

results = {} 
for type in ['type1', 'type2']: 
    results[type] = [] 
    for input_vector in input_vectors: 
     results.append(f(input_vector, matrices[type], vectors[type])) 

입니다. 그러나 벡터의 목록을 통해 매핑하고자하는 함수가 단순히 벡터가 아닌 그 입력으로 가져 오는 문제를 해결하는 방법을 모르겠습니다.

나는 람다 함수를 절인 할 수 없기 때문에 작동하지 않습니다 그러나

from multiprocessing import Pool 
p = Pool(4) 
for type in types: 
    p.map(lambda x: f(x, matrices[type], vectors[type] , input_vectors)) 

같은 것을 쓰고 싶습니다. 작동하는 한 가지 방법은 각 벡터에 곱하기를 원하는 행렬을 추가하는 것입니다. 물론 메모리를 사용하는 것은 불가능합니다.

내 수수께끼를 우아하게 해결하는 방법에 대한 의견이 있으십니까? 내가 좋아하는 것이 무엇


행렬과 함께 번성하는 벡터의 사본을 가지고있는 풀의 각 요소에 대해,하지만 난 multiprocessing에서이 작업을 수행하는 방법을 모르겠어요. 당신이 Pool를 시작할 때마다 아이에게 전체 matricesvectors 목록을 통과하려는 경우

def f(matrix, vector, input_vector): 
    return np.dot(matrix, input_vector) + vector 

results = {} 
for type_ in types: 
    func = partial(f, matrices[type_], vectors[type_]) 
    results[type_] = p.map(func, input_vectors) 

하고 당신이 호출 할 때 type을 통과 :

답변

3

사용 functools.partialmap에 여러 인수를 전달합니다 map도 가능합니다./initargs 인수를 multiprocessing.Pool으로 사용하여 목록을 전달한 다음 initializer 함수 내에서 전역으로 만듭니다. 그러면 각 하위 프로세스 내에서 글로벌하게됩니다.

matrices = vectors = None 

def init(_matrices, _vectors): 
    global matrices, vectors 
    matrices = _matrices 
    vectors = _vectors 


def f(type_, input_vector): 
    return np.dot(matrices[type_], input_vector) + vectors[type_] 

def main(): 
    # <declare matrices, vectors, input_vectors here> 
    p = multiprocessing.Pool(initializer=init, 
          initargs=(matrices, vectors)) 
    results = {} 
    for type_ in ['type1', 'type2']: 
     func = partial(f, type_) 
     results[type_] = p.map(func, input_vectors) 

if __name__ == "__main__": 
    main() 
+0

답장을 보내 주셔서 감사합니다. 단지 하위 쿼리인데,이 방법은 각 프로세스가 매트릭스의 개별 복사본을 가질 수있게 하는가? 멀티 프로세싱이 올바르게 이해된다면, 그럴 것입니다 ... – 5xum

+0

@ 5xum 개념 상, 예, 각 프로세스는 별도의 복사본으로 끝납니다. 이제 실제로, 리눅스와 같이'os.fork()'를 지원하는 플랫폼을 사용한다면, 각 프로세스는'matrices'의 "copy-on-write"버전을 얻습니다. 즉,'matrices'를 수정하지 않는 한, 대부분의리스트는 실제로 프로세스들 사이에서 공유 될 것입니다.그러나 수정을 시도하자마자 수정 작업을 수행하는 프로세스는 수정할 커널 목록에있는 커널 페이지에 대해 별도의 복사본을 만듭니다. – dano

+0

감사합니다. 나는 윈도우를 사용하고 있지만 매트릭스가 각 프로세스에 복사되지 않는다면 하나의 매트릭스가 (np.dot() 명령을 실행하는 동안) 대부분의 시간을 잠글 수 있고 나는 내가 필요로하는 스피드 업을 얻지 못할 것이다. – 5xum