2009-12-01 7 views
15

나는 multiprocessing 모듈과 병렬 처리하기를 원하는 많은 "당혹스럽지 않은"병렬 프로젝트를 실행합니다. 그러나 대용량 파일 (2GB 이상)을 읽고, 줄 단위로 처리하고, 기본 계산을 실행 한 다음 결과를 작성하는 작업이 종종 포함됩니다. 파이썬의 멀티 프로세싱 모듈을 사용하여 파일을 분할하고 처리하는 가장 좋은 방법은 무엇입니까? Queue 또는 JoinableQueuemultiprocessing에 사용해야합니까? 또는 Queue 모듈 자체입니까? 또는, 파일 풀을 반복 실행하여 multiprocessing을 사용하여 프로세스 풀에 매핑해야합니까? 필자는 이러한 접근법을 실험했지만 오버 헤드는 데이터를 한 줄에 하나씩 분배하는 데 엄청난 양입니다. 필자는 cat file | process1 --out-file out1 --num-processes 2 | process2 --out-file out2을 사용하여 첫 번째 프로세스 입력의 특정 비율을 두 번째 입력 (this post 참조)에 직접 전달하는 가벼운 파이프 필터 설계에 착수했지만 완전한 솔루션이 Python에 포함되도록하고 싶습니다.파이썬에서 대용량 파일을 멀티 프로세싱을 위해 나누는 가장 좋은 방법은 무엇입니까?

놀랍게도 Python 설명서는 multiprocessing 설명서의 프로그래밍 가이드 라인에 대한 긴 섹션에도 불구하고이를 수행하는 표준 방법을 제안하지 않았습니다.

감사합니다, 빈스

추가 정보 : 라인 당 처리 시간이 달라집니다. 일부 문제는 빠르며 간혹 I/O 바운드가 아니며 일부는 CPU 바운드입니다. CPU 종속적 인 비 종속적 인 작업은 처리 기능에 데이터를 할당하는 비효율적 인 방법조차도 벽시계 시간 측면에서 여전히 유리할 수 있도록 병렬화로 인해 게시를 얻습니다.

주요 예는 라인에서 필드를 추출하고 다양한 비트 플래그를 검사하며 특정 플래그가있는 라인을 완전히 새로운 포맷으로 새 파일에 쓰는 스크립트입니다. 이것은 I/O 바운드 문제처럼 보이지만 파이프가있는 저렴한 동시 버전으로 실행하면 약 20 % 빨라졌습니다. 내가 풀과 맵으로 실행하거나 multiprocessing에 큐를 넣을 때 항상 100 % 이상 느려집니다.

+0

이것은 대담한 스크립팅 언어에 대한 내 큰 불만입니다. 동시 처리는 스레드가없는 고통입니다. . 물론 완료 할 수는 있지만 스레드 및 잠금 모델을 사용하면 작업이 훨씬 간단 해집니다. –

+0

쓰레딩 된 "병렬"버젼은 쓰레드가 프로세스보다 빠르게 작성된다는 사실을 제외하고 결코 빠르지 않을 것입니다.GIL은 CPU 바인딩 된 다중 스레드 프로그램의 큰 병목입니다. 또한 프로세스/스레드간에 공유해야하는 변경 가능한 객체가 없기 때문에 멀티 프로세싱보다 멀티 스레딩이 실제로 필요하지 않습니다. – Vince

+0

@Vince 실제로, 그것은 모두 정확한 상황에 의존합니다. 너 안에는 절대로 없을거야. 다른 사람들에게는 그것이 가능할 수도 있습니다. 요점은 (C에서) 수행해야했던 동시 작업의 대부분에 대해 스레드와 잠금이 훨씬 간단한 모델을 제공 할 때 적절한 IPC에 필요한 여분을 사용하는 것은 거의 정당화되지 않았다는 것입니다. 다른 시스템에서보다 잘 확장해야하는 더 큰 문제의 경우에는 다른 이야기입니다. –

답변

8

최고의 아키텍처 중 하나는 이미 Linux OS의 일부입니다. 특별한 라이브러리가 필요하지 않습니다.

"팬 아웃"디자인이 필요합니다.

  1. "주"프로그램은 파이프로 연결된 여러 하위 프로세스를 만듭니다.

  2. 주 프로그램은 해당 서브 프로세스에 줄을 처리하는 데 필요한 최소 필터링을 수행하는 파이프에 줄을 쓰는 파일을 읽습니다.

각 하위 프로세스는 stdin에서 읽고 쓰는 개별 프로세스의 파이프 라인이어야합니다.

대기열 데이터 구조, 즉 메모리 내 파이프 라인이 필요하지 않습니다. 두 개의 동시 프로세스 사이의 바이트 대기열입니다.

+0

멀티 프로세싱 모듈에 파이프가 있으므로 파이썬에서이 접근법을 구현하는 방법을 살펴 보겠습니다. 원래 게시물에서 볼 수 있듯이, 나는 쉘에서이 접근법을 사용하여 큰 성공을 거둔다. 나는 파이프와 데이터 병렬성을 결코 달성 할 수 없다고 생각하지 않았다. – Vince

+0

간단한 쉘 파이프가 이상적인 병렬 처리 형태입니다. Linux가 가장 잘하는 부분입니다. 종종 완벽한 솔루션입니다. –

+0

결과는 다음과 같습니다. http://github.com/vsbuffalo 및 32 CPU 시스템의 결과 (http://paste.pocoo.org/show/154252/). 감사합니다 S.Lott! – Vince

1

파일 형식에 따라 크게 달라질 수 있습니다.

어디서나 분리 할 수 ​​있습니까? 아니면 새로운 라인에서 분할해야합니까? 아니면 당신이 객체 정의의 끝에서 그것을 분리했는지 확인해야합니까?

파일을 분할하는 대신 os.lseek을 사용하여 같은 파일에서 여러 독자를 사용하여 파일의 해당 부분으로 이동해야합니다.

업데이트 : 포스터는 새 줄을 나누고 싶다고 덧붙였다. 그런 다음 다음을 제안합니다.

네 가지 프로세스가 있다고 가정 해 보겠습니다. 그런 다음 간단한 해결책은 파일의 0 %, 25 %, 50 % 및 75 %로 os.lseek를 지정하고 첫 번째 새 행을 칠 때까지 바이트를 읽는 것입니다. 이것이 각 프로세스의 출발점입니다. 이 작업을 위해 파일을 분할 할 필요가 없으며 각 프로세스의 큰 파일에서 올바른 위치를 찾고 거기에서 읽기 시작할 수 있습니다.

+0

줄 바꿈으로 분할. – Vince

+0

귀하의 경우에 os.lseek를 사용하는 방법을 설명하기 위해 설명을 업데이트했습니다. –

4

줄을 처리하는 방법에 대해 언급하지 마십시오. 아마도 가장 중요한 정보 일 것입니다.

각 줄은 독립적입니까? 계산은 한 줄에 의존하여 다음 줄로 진행됩니까? 블록 단위로 처리해야합니까? 각 라인의 처리 시간은 얼마나 걸립니까? 마지막 단계에서 데이터를 "모두"통합해야하는 처리 단계가 있습니까? 또는 중간 결과를 버리고 총 누계를 유지할 수 있습니까? 파일 수를 스레드 수로 나눠서 파일을 초기 분할 할 수 있습니까? 아니면 당신이 그것을 처리하면서 자랄 수 있습니까?선이 독립적이며, 파일이 성장하지 않는 경우

는 당신이 필요로하는 유일한 조정은 노동자의 각각에 "시작 주소"와 "길이"을 경작하는 것입니다; 그들은 파일을 독립적으로 열어서 탐색 할 수 있으며 결과를 조정해야합니다. 아마도 N 개의 결과가 대기열로 돌아 오기를 기다리는 것입니다.

줄이 독립적 인 경우 대답은 파일 구조에 크게 의존합니다.

+0

죄송합니다. 각 파일은 독립적이며 아무것도 종속적이지 않으며 공유되지 않습니다 (선택적 카운터 제외). 고전적인 예는 라인을 가져 와서 유지할지 여부를 결정하고, 보관 된 라인에 대해 사소한 계산을 수행하고, 이러한 계산을 포맷 한 다음 해당 라인을 파일에 기록하는 함수입니다. 그런 다음 모든 파일을 별도의 프로세스에서 함께 연결할 수 있습니다. 파일 탐색과 관련하여 파이썬에서 바이트 카운트를 통해 검색이 이루어지기 때문에 라인을 바이트와 매치하는 데 복잡성이 생길 수 있습니다. 그만한 가치가 있니? – Vince

+0

PS : 파일이 커지지 않으며 중간 결과가 파일에 추가됩니다 (I/O 쓰기 충돌을 방지하기 위해 프로세스 당 하나의 파일). 이것은 진실로 당황스럽게 평행 한 문제입니다. – Vince

1

당신이 특별히 파이썬에 대해 물었 습니다만, 하둡 (http://hadoop.apache.org/)을 보도록 권장합니다 :이 문제를 해결하기 위해 특별히 고안된지도 및 축소 알고리즘을 구현합니다. 각 프로세스를 가진 것은 Queue 통해 다음 줄을 읽어 대신

+0

이 문제를 해결할 수 있는지 아직 알 수 없습니다. 다른 사람들이 지적했듯이, 우리는 문제에 대해 충분히 알지 못합니다. –

+1

@ San Jacinto ... "그들은 대용량 파일 (2GB 이상)을 읽고, 한 줄씩 처리하고, 기본 계산을 실행 한 다음 결과를 작성하는 것과 관련이 있습니다." 특정 구현 세부 사항을 제공하지만 일반적인 관찰은 제공합니다. 진정해. – Escualo

+0

전에 hadoop과 map/reduce를 사용했습니다. 나는 둘 다 좋아하고 map/reduce는 여기에 적용될 수있다. Hadoop은 HFS (IIRC)에서 일부 I/O 문제를 해결합니다. map/reduce 이전 단계에 대해 묻고 있는데, 어떤 접근 방식은 파일을 매핑하여 함수를 매핑합니다. 대기열? 파일을 반복 할 수 있습니까? – Vince

0

실행 시간이 긴 경우

행운을 빌어 요, 프로세스가 라인의 배치를 읽을 수 있습니다. 이 방법으로 오버 헤드가 여러 라인 (예 : 수천 또는 그 이상)으로 상각됩니다.

6

한 전략은 각 노동자를 할당 할 수있는 8 명 개의 노동자가 당신이 다음에 할당 처리 할 경우 숫자 0 7. 근로자에 ​​숫자 0은 최초의 기록을 읽고 그 다음 7을 건너 뛰고 처리 등을 8 레코드를 처리하기 위해 계속 수 있도록 오프셋 (offset) 작업자 번호 1은 두 번째 레코드를 읽은 다음 7을 건너 뛰고 9 번째 레코드를 처리합니다 .........

이 구성표에는 여러 가지 장점이 있습니다. 파일이 얼마나 균등하게 분할되어 있느냐에 상관없이 동일한 시스템의 프로세스가 대략 동일한 비율로 처리되고 동일한 버퍼 영역을 사용하므로 과도한 I/O 오버 헤드가 발생하지 않습니다. 파일을 갱신하지 않으면 개별 스레드를 다시 실행하여 실패로부터 복구 할 수 있습니다.

1

프레드릭 룬트 (Fredrik Lundh)의 Some Notes on Tim Bray's Wide Finder Benchmark은 좋은 충고를 많이, 매우 유사한 사용 사례에 대한 흥미로운 읽기입니다. 여러 다른 저자들도 같은 것을 구현했지만, 일부는 기사에서 링크되어 있지만, "파이썬 넓은 파인더"또는 더 많은 것을 찾기 위해 인터넷 검색을해볼 수도 있습니다. (어쨌든 multiprocessing 모듈을 기반으로 한 솔루션이 있었지만 더 이상 사용할 수없는 것 같습니다.)

+0

많은 제출물의 출처를 추적하기가 너무 어렵습니다. widefinder/widefinder2의 항목에서 배울 수있는 유용한 기술이 많이 있습니다. – jmanning2k