복붙노트

[PYTHON] NumPy 대 다중 처리 및 mmap

PYTHON

NumPy 대 다중 처리 및 mmap

파이썬의 멀티 프로세싱 모듈을 사용하여 대다수의 배열을 병렬로 처리하고 있습니다. 배열은 마스터 프로세스에서 numpy.load (mmap_mode = 'r')를 사용하여 메모리 맵핑됩니다. 그 후, multiprocessing.Pool () 프로세스를 포크 (전설).

나는 다음과 같은 행을 제외하고는 모든 것이 잘 작동하는 것처럼 보인다.

단위 테스트 로그에. 그럼에도 불구하고 테스트는 잘 통과합니다.

무슨 일이 벌어지는 지 알아?

Python 2.7.2, OS X, NumPy 1.6.1 사용.

최신 정보:

일부 디버깅 후 Pool.imap 호출에 대한 입력으로 메모리 매핑 된이 numpy 배열 (작은 조각)을 사용하는 코드 경로에 대한 원인을 찾아 냈습니다.

분명히 "문제"는 다중 처리 방식과 관련이 있습니다 .Pool.imap은 입력을 새 프로세스에 전달합니다. 즉, pickle을 사용합니다. mmaped numpy 배열에서는 작동하지 않으며, 내부에서 오류로 연결되는 부분이 있습니다.

로버트 커른 (Robert Kern)이이 문제를 다루는 것으로 보입니다. 그는 메모리 매핑 된 배열에서 가져온 imap 입력에 대한 특수 코드 경로를 만드는 것이 좋습니다. 생성 된 프로세스에서 동일한 배열을 수동으로 메모리 매핑합니다.

이것은 오히려 오류와 여분의 메모리 복사본으로 살기 때문에 너무 복잡하고 추한 것입니다. 기존 코드를 수정하는 데 더 가벼운 다른 방법이 있습니까?

해결법

  1. ==============================

    1.내 평소 접근 (여분의 메모리 복사본을 가지고 살 수있는 경우)은 한 프로세스에서 모든 IO를 수행 한 후 작업자 스레드 풀로 보내야합니다. memmapped 배열의 조각을 메모리에로드하려면 x = np.array (data [yourslice]) (data [yourslice] .copy ()는 실제로이 작업을 수행하지 않으므로 혼동을 일으킬 수 있습니다.)

    내 평소 접근 (여분의 메모리 복사본을 가지고 살 수있는 경우)은 한 프로세스에서 모든 IO를 수행 한 후 작업자 스레드 풀로 보내야합니다. memmapped 배열의 조각을 메모리에로드하려면 x = np.array (data [yourslice]) (data [yourslice] .copy ()는 실제로이 작업을 수행하지 않으므로 혼동을 일으킬 수 있습니다.)

    먼저 몇 가지 테스트 데이터를 생성 해 봅시다.

    import numpy as np
    np.random.random(10000).tofile('data.dat')
    

    다음과 같이 오류를 재현 할 수 있습니다.

    import numpy as np
    import multiprocessing
    
    def main():
        data = np.memmap('data.dat', dtype=np.float, mode='r')
        pool = multiprocessing.Pool()
        results = pool.imap(calculation, chunks(data))
        results = np.fromiter(results, dtype=np.float)
    
    def chunks(data, chunksize=100):
        """Overly-simple chunker..."""
        intervals = range(0, data.size, chunksize) + [None]
        for start, stop in zip(intervals[:-1], intervals[1:]):
            yield data[start:stop]
    
    def calculation(chunk):
        """Dummy calculation."""
        return chunk.mean() - chunk.std()
    
    if __name__ == '__main__':
        main()
    

    그리고 대신 np.array (data [start : stop])를 사용하기로 전환하면 문제를 해결할 수 있습니다.

    import numpy as np
    import multiprocessing
    
    def main():
        data = np.memmap('data.dat', dtype=np.float, mode='r')
        pool = multiprocessing.Pool()
        results = pool.imap(calculation, chunks(data))
        results = np.fromiter(results, dtype=np.float)
    
    def chunks(data, chunksize=100):
        """Overly-simple chunker..."""
        intervals = range(0, data.size, chunksize) + [None]
        for start, stop in zip(intervals[:-1], intervals[1:]):
            yield np.array(data[start:stop])
    
    def calculation(chunk):
        """Dummy calculation."""
        return chunk.mean() - chunk.std()
    
    if __name__ == '__main__':
        main()
    

    물론 이것은 각 청크의 여분의 메모리 내 복사본을 만듭니다.

    결국에는 memmapped 파일을 전환하고 HDF와 같은 파일로 쉽게 전환 할 수 있습니다. 데이터가 다차원 인 경우 특히 그렇습니다. (필자는 h5py를 권하고 싶지만 데이터가 "테이블과 같은"경우 pyTables가 좋습니다.)

    어쨌든 행운을 비네!

  2. from https://stackoverflow.com/questions/9964809/numpy-vs-multiprocessing-and-mmap by cc-by-sa and MIT license