2013-01-09 2 views
2

제 질문은 파이썬의 멀티 프로세싱 모듈에 관한 것입니다. 가장 단순한 형태에서 , 내 질문은 다음과 같은 코드의 이상한 행동입니다 : 실행 후멀티 프로세싱 모듈 (파이썬)의 맵 메서드에서의 할당

import numpy as np 
from multiprocessing import Pool 

x = np.random.random(100) 
y = np.random.random(100) 
y2 = y[:] 

def I(i): 
    y[i] = x[i] 

pool = Pool() 
pool.map(I,range(100)) 

, 내 희망은 Y =의 X입니다. 그러나 y = y2가됩니다. (과제물이 작동하지 않습니다.) 왜 이런 일이 발생합니까? f (x [i])를 계산하고이를 y [i]에 할당하는 가장 좋은 방법은 무엇입니까?

+0

사실, 파이썬은'다중 처리. 프로세스 '사이의 자원을 잘 공유하지 않습니다. [zeromq divide and conquer pattern] (http://zguide.zeromq.org/page:all#Divide-and-Conquer)를'multiprocessing.Process'와 함께 사용하는 것이 좋습니다. 리소스를 공유하고 싶다면 스레드를 사용하십시오 (ThreadPools에는 라이브러리가 있습니다). – bitcycle

답변

1

작업을 수행하는 데 Pool에서 사용하는 프로세스간에 동기화되는 내용에 대해 생각해 보면 그리 놀라운 것은 아닙니다. I 함수의 인수와 반환 값만 현재 코드에서 동기화되므로 xy은 호출 프로세스에서 원래 값을 유지합니다.

현재 코드가 최소한의 테스트 케이스라고 생각합니다. Pool.map을 사용하여 배열을 다른 배열로 복사하는 의미있는 구현이 없으므로 까다로운 문제입니다. 여기에 사소한 솔루션입니다,하지만 난 그게 진짜 작업이 무엇이든에 일반화 확실하지 않다 : 이것은 (아무것도 그것으로 수행되지 않습니다) 다른 프로세스를 통해 x의 각 값을 전달하고 결과 값은

import numpy as np 
from multiprocessing import Pool 

def I(v): 
    return v 

if __name__ == "__main__": # this boilerplate is required on on Windows 
    x = np.random.random(100) 
    y = np.random.random(100) 

    pool = Pool() 
    y[:] = pool.map(I, x) 

    print(x == y) # [True, True, True, ...] 

다시 전달되고 y에 할당됩니다 (pool.map는 목록을 반환 함). 그것은 꽤 어리 석다.

약간 더 정교한 접근 방식은 Pool 생성자에서 initializerinitargs 인수를 사용하여 작업자 프로세스에 걸쳐 x를 복사 할 수 있습니다. 여기 않는 예제가 :

import numpy as np 
from multiprocessing import Pool 

def I(index): 
    return x[index] 

def setup(value): 
    global x 
    x = value 

if __name__ == "__main__": 
    x = np.random.random(100) 
    y = np.random.random(100) 

    pool = Pool(initializer=setup, initargs=(x,)) 
    y[:] = pool.map(I, range(100)) 

    print(x == y) # [True, True, True, ...] 

한 방향으로 만 복사하는 x 불구하고 주. I이 값을 수정하면 변경 내용이 프로세스간에 동기화되지 않습니다.

작업이 원본 및 대상 배열 모두에 대해 동기화 된 액세스가 실제로 필요한 작업 인 경우 multiprocessing.Array을 시도해보십시오. 직접적인 경험은 없지만 y을 동기화 된 버전으로 대체 할 수 있어야합니다. 불행히도, 동기화가 여러분의 프로그램을 느리게 할 것이라고 생각합니다. 정말 필요하지 않으면 그렇게하지 마십시오!

+0

답변 해 주셔서 감사합니다. 모든 변수가 동기화되는 것은 아닙니다. (비록 "동기화"의 정확한 의미를 이해하지 못한다.) 프로세스는 x 변수를 상속받는 것처럼 보인다. 두 번째 코드에서 'pool = Pool()'으로 복사하는 것으로 충분하다고 생각합니다. – ywat

+0

@ user1878808 "syncronized"란 말은 프로세스에서 수정할 수있는 변수를 설정했으며 모두 동일한 상태를 볼 수 있음을 의미합니다. 그렇게하기가 어렵고 많은 오버 헤드 없이는 불가능할 수도 있습니다. 전 세계 변수이기 때문에'x' 변수는 원래 코드에서 작동했다고 생각합니다. 그래서'Pool'이 생성 된 후 작업자 프로세스가 fork 될 때 복사됩니다. Windows에는'fork' 함수가 없기 때문에, 코드는 거기에서 똑같이 작동하지 않을 것입니다 (x는 존재할 것입니다, 그러나 다른 임의의 값을 포함 할 것입니다). 내 버전에서는 유일하게 전역 변수가 함수입니다. – Blckknght

+0

@Blackknght 추가 코멘트 주셔서 감사합니다. Linux (Ubuntu 12.04)를 사용하고 있습니다. 나는 휴대용 코드를 작성하는 것을 명심 할 것이다. – ywat