2013-08-17 2 views
0

다른 알려진/신뢰할 수있는 노드 (주로 SQLite 데이터베이스에 저장 됨)에서 들어오는 데이터를 동시에 처리하는 작은 p2p 응용 프로그램을 만들고 싶습니다. 이러한 노드를 인식하기 위해서는 연결시 각 노드가 자신을 소개하므로 내 응용 프로그램은이 노드를 직접 또는 간접적으로 다른 노드를 통해 알 수 있는지 여부를 확인해야합니다. 따라서 분명히 처리 시간을 필요로하는 그래프 검색을 수행해야하며 별도의 프로세스 (또는 여러 개의 작업자 프로세스)로 아웃소싱하고 싶습니다. 아래의 두 번째 질문을 참조하십시오. 또한 경우에 따라 그래프를 조정하고 새 가장자리 또는 정점을 추가해야합니다.파이썬 3에서 그래프를 동시에 검색

4 개의 작업자 프로세스이 비동기 입출력을 통해 들어오는 연결을 수락하고 처리한다고 가정 해 보겠습니다. 그래프에 액세스 (읽기/수정)하는 가장 좋은 방법은 무엇입니까? 검색 결과를 어떻게 든 전달해야하기 때문에 단일 대기열은 분명히 읽기 액세스의 트릭을 수행하지 않습니다.

따라서,이를 수행하는 한 가지 방법은 그래프 검색 프로세스로 채워질 이벤트 대기열에 추가 할 수있는 또 다른 대기열입니다. 이벤트 루프는 그 결과를 핸들러로 전달할 수 있습니다. 그러나이 이벤트/콜백 기반 방식을 사용하면 해당 소켓을 콜백에 전달하고 대기열에 항상 전달해야합니다. 소켓은 picklable이 아니기 때문에 nasty입니다. (사실 콜백이 스파게티 코드로 이어지지는 않는다.)

또 다른 아이디어는 각 수신 연결에 대해 그래프 프로세스에 대한 파이프를 작성한 다음 그래프 측면에서 비동기 I/O도. 그러나 콜백을 피하기 위해 정확하게 이해한다면 yield from (즉, tulip/PEP 3156)을 사용하는 비동기 I/O 라이브러리가 필요합니다. 다른 옵션이 있습니까? 비동기 I 에/O에 대해서는

그래프의 측면 :이 확실히 많은 들어오는 한 번에 요청하지만, 그래프 조회를 수행하는 것은 CPU 집약적 인 작업입니다을 처리하는 가장 좋은 방법입니다, 따라서 여러 작업자 스레드 또는 프로세스를 사용하여 이익을 수. 문제는입니다 : 다중 스레드는 공유 데이터를 허용하지만 Python의 GIL은 성능 이점을 다소 부인합니다. 다른 한편으로는 여러 프로세스가이 문제가 없지만 어떻게 서로 공유하고 데이터를 동기화 할 수 있습니까? (제게는 그래프를 나누는 것이 불가능한 것처럼 보입니다.) 좋은 방법으로이 문제를 해결할 방법이 있습니까? 또한 멀티 스레딩/멀티 프로세싱과 비동기 I/O를 섞어 성능면에서 의미가 있습니까?

답변

1

마지막 질문에 답하십시오. 하지만, IMHO, 문제는 : 이벤트와 스레드를 혼합하는 것이 의미가 있습니까? 하이브리드 동시성 모델에 대한이 기사에서 확인할 수 있습니다. http://bibliotecadigital.sbc.org.br/download.php?paper=3027

팁 : 하나의 프로세스와 튤립 모델과 같은 이벤트 루프로 시작하십시오. 튤립을 사용하여 이벤트 + 비동기 I/O (및 스레드 또는 기타 프로세스)를 콜백없이 수행하는 방법을 설명하려고 노력할 것입니다.

당신은 튤립 코 루틴 (check_incoming)해야 accept = yield from check_incoming() 같은 것을 가질 수 있으며,이 함수 내에서이 스레드/프로세스 풀의 그래프 검색을 실행하는 loop.run_in_executor()를 사용할 수 (나는 나중에에 대한 자세한 설명하겠습니다) . 이 함수 run_in_executor()은 Future를 반환하며, yield from tasks.wait([future_returned_by_run_in_executor], loop=self)도 사용할 수 있습니다. 다음 단계는 result = future_returned_by_run_in_executor.result()이고 마지막으로 True 또는 False을 반환합니다.

프로세스 풀에서는 선택 가능한 개체 만 실행하고 반환 할 수 있어야합니다.이 요구 사항은 문제가 아니지만 그래프 작업이 함수에 자체 포함되어 있어야하며 그래프 인스턴스를 어떻게 든 가져와야 함을 암시합니다. 쓰레드 풀은 GIL 문제가 있습니다. 왜냐하면 'get-gil-conflicts'로 이어질 수있는 CPU 바운드 작업에 대해 언급했기 때문에 새로운 Python 3.x GIL에서 개선되었습니다. 두 솔루션 모두 한계가 있습니다 ...

풀 대신에, 그래프 작업을 관리하고 유닉스 도메인 소켓으로 두 프로세스를 연결하기 위해 자체 이벤트 루프를 사용하여 다른 단일 프로세스를 가질 수 있습니다.

이 두 번째 프로세스는 첫 번째 프로세스와 마찬가지로 들어오는 연결을 받아 들여야하지만 (지금은 알려진 출처), 앞서 말한 것처럼 스레드 풀을 사용할 수 있지만 첫 번째 스레드와 "충돌"하지 않습니다 두 번째 이벤트 루프에서만 이벤트 루프 프로세스 (외부 클라이언트를 처리하는 프로세스). 동일한 그래프 인스턴스를 공유하는 스레드는 잠금/잠금 해제가 필요합니다.

희망이있었습니다.

+0

오랫동안 회신 해 주셔서 감사합니다. 당신이 쓴 모든 것을 이해할 수 있을지 모르겠다. 들어오는 외부 요청을 처리하는 하나의 프로세스/이벤트 루프가 있고 작업자 스레드 풀 (스레드 안전 프로그래밍이 필요함)을 제공하여 실제 검색을 수행하는 다른 하나를 제안하고 있는가? ? 어쨌든 나는 아직도 그래프 검색의 성능이 실제로 스레드를 사용함으로써 이익을 얻을 것이라고 확신하지 못한다. – balu

+0

마지막으로, 3 단락에서 쓴 것을 자세히 설명해 주시겠습니까? 좀 혼란 스럽네요. 정확히'check_incoming()'이해야 할 일은 무엇입니까? 나는 단지 새로운 들어오는 (내부) 검색 요청을 산출 할 것으로 기대한다. 또한'run_in_executor()'에 의해 반환되는 미래 **에서 tasks.wait ([future_returned_by_run_in_executor], loop = self)'**에서 yield 할 수 있습니까? 어쩌면 코드 예제를 줄 수 있습니까? – balu

+0

안녕하세요! 첫 번째 의견에 대해 : 예, 2 각 하나의 자신의 이벤트 루프와 함께 처리 ... 나는 스레드 풀에 대해 언급했지만 그것을 사용하지 않을 것이다 .. 스레드는 CPU가 실제로 바인딩 된 경우 이익을 얻을 수 없다 ..하지만 그렇다하더라도, 이것은 파이썬 3보다 2보다 우수합니다. –

관련 문제