2013-04-01 2 views
7

몇 가지 콜백 함수가 있으며 여러 프로세스로 실행하고 부모 프로세스의 신호를 통해 종료하도록하고 싶습니다.파이썬에서 다중 프로세스를 사용하여 자식 프로세스를 올바르게 종료하는 방법

내 현재의 방법은 multiprocessing.Value으로 공유 c_bool을 만들고이를 True으로 설정 한 다음 작성한 모든 프로세스에 배포합니다. 그때 그들의 최종 루프 종료를 완료합니다 내 부모 프로세스 및 모든 자식 프로세스에서 False에 부울을 전환 할 수 있습니다

while myC_bool: ...keep running... 

: 내 프로세스를 모두과 같이 공유 BOOL을 사용하여 while 루프를 실행합니다.

나는 많은 사람들에게 이야기를 들었으며 다중 처리를 사용할 때 공유 메모리를 사용하지 않도록 노력해야한다는 문서를 읽었습니다. 나는 이것을 피하는 가장 좋은 방법은 프로세스를 대몬 화하고, 사용자 정의 시그널 핸들러를 제공하고, sigint/sigterm/etc를 보내라는 말을 들었습니다 ...

제 질문은 bool을 사용하여 루프를 사용하고 부모 프로세스에서 값을 변경하는 경우에만 여러 하위 프로세스에서 모든 하위 프로세스를 신속하고 안전하게 종료 할 수있는 적합한 솔루션을 읽습니다. 나는 모든 어린이들에게 공유 된 bool을 보도록하는 오버 헤드가 적어서 x 개의 수의 sigints를 그들에게 보낸다.

더 나은 해결책이 될 수 있습니까? 그렇다면 이유를 이해하는 데 도움이되고 싶습니다.

답변

9

좋은 많은 이유가 솔루션으로 가고 있습니다

  • 그것은 신호보다 더 생각하는 것이 더 쉽습니다.
  • 처리 할 플랫폼 간 문제가 줄어 듭니다.
  • 이미 이런 식으로 작동하는 코드가 있습니다.
  • 장래에 원할 경우 "정상적인 종료"메커니즘을 쉽게 추가 할 수 있습니다.

... 등등.

multiprocessing과 근본 OS 프리미티브가 신경 쓸 필요가없는 모든 플랫폼에서 작동하지 않을 것이라는 것을 증명하지 못한다면 모든 액세스마다 Lock 또는 다른 것을 넣어야합니다. 공유 된 bool에게. 그게 정확히 복잡하지는 않지만 한번 해본 적이 있다면 예를 들어 Event을 공유 bool없이 사용하면 훨씬 간단해질 수 있습니다.

어쨌든, 그 중 하나가 당신의 이유라면 나는 그렇게 말할 것입니다. 그러나 귀하의 질문에 따라, 당신은 실제로 때문에 성능이를 선택 :

내가 그들

에 sigints의 X 번호를 전송하는 것보다 그냥 하나의 공유 부울 보는 모든 어린이를위한 적은 오버 헤드가 기분

그 이유가 사실이라면, 틀림없이 틀 렸습니다. 아이들은 매번 루프를 통해 공유 된 bool을보고 (그리고 공유 잠금을 획득해야합니다!), 신호는 각 자식에게 한 번만 보내야합니다. 따라서 오버 헤드가 거의 확실하게 이렇게 높을 것입니다.

하지만 실제로 자식 프로세스 당 하나의 신호를 보내는 오버 헤드 나 프로세스 당 루프 당 한 번 프로세스 간 잠금을 잡는 오버 헤드가 유용한 프로그램의 병목 현상에 가까울 것이라고 상상할 수 없습니다. 오버 헤드도 여기에서 처음부터 중요합니까? 가장 간단한 방법으로 가장 의미있는 것을하십시오.

+0

답장을 보내 주셔서 감사합니다. 사용하고있는 방법에 대한 비판에 감사드립니다. 나는 다른 프로세스에 있어도 값을보기 위해 잠금을 획득해야한다는 사실을 간과했다. 공유 된 값을 피하는 이유는 여러 프로세스를 사용하는 이점을 방해하는 프로세스가 스레드와 유사 해지기 때문입니다. – LISTERINE

+0

@리스 스틴 : 나는 그런 식으로 생각하지 못했지만, 그래, 그것을 보는 좋은 방법입니다. 스레드에 대한 주요 단점은 공유 (변경 가능) 값이 메시지 전달보다 추론하기가 더 어렵다는 것이고 동시 프로그래밍은 인종을 고려하지 않고 충분히 어렵다는 것입니다. CPython에 특정한 단점은 GIL이 스레드 된 코드가 본질적으로과 동기화되어 병렬 대신 거의 직렬로 끝나는 것을 의미합니다. 명시 적 공유 값은 암시 적 공유만큼 나쁘지 않으며 한 값 주변의 잠금은 GIL만큼 나쁘지는 않지만 스레딩의 단점으로 돌아갑니다. – abarnert

+0

@LISTERINE : ... 말하자면, 다음과 같은 이유로 이러한 기능이 존재한다고 언급 할 가치가 있습니다. 때로는 멀티 프로세싱으로 시작하여 스레딩으로 한 발을 내딛는 것이 (a) 스레딩에서 시작하여 멀리 이동하려는 것보다 훨씬 더 나은 대답입니다. (b) 전체 알고리즘을 다시 구성하여 공유하지 않고 코드화 할 수 있습니다. – abarnert

2

공유 변수를 수정하는 사람은 신중해야하므로 잘해야합니다.

여러 가지 가능한 솔루션이 있습니다. 예 : multiprocessing.Event을 사용하고 프로세스가 설정되면 종료되도록하십시오. 또는 multiprocessing.Connection 개체 (파이프에서)를 사용하십시오. 후자는 부모와 자녀 사이의 양방향 의사 소통에 사용될 수 있습니다. 멈추라는 아이들에게 보내는 신호처럼, 부모에게 확인이 뒤따른 것.

0

"이 일을하지 마십시오"라고 말하는 사람들은 잘못입니다. 공유 메모리의 요점은 멀티 프로세서 사이에서 메모리를 공유하는 것이고 이것이 바로 당신이하고있는 일입니다.

1) 간단하고 2) 작동하는 솔루션이 있습니다. 신호/데몬 접근법은 1) 정말 멋지다. 2) 올바르게 코드를 작성하기가 어렵다. 3) 이해하기가 훨씬 어렵다.

당신의 접근법에서 볼 수있는 유일한 함정은 프로세스가 CPU의 캐시에서 부울의 부실 사본을 볼 수 있고 시스템 종료시 약간 지연 될 수 있다는 것입니다. 캐시를 플러시하여 이러한 일이 발생하지 않도록하는 방법이 있지만 대부분의 응용 프로그램에서는 캐시 플러시가 자주 자동으로 자주 발생하기 때문에 필요하지 않을 것입니다.

지상에 서십시오.

+0

"대부분의 응용 프로그램에서 캐시 플러시는 자주 자동으로 자주 발생합니다." 관심이있는 모든 플랫폼에서 응용 프로그램에 대해 자주 (또는 항상!) 일어나는 것을 확실히 모르는 경우 명시 적으로 동기화해야합니다. 그렇지 않으면, 첫 번째 큰 데모에서 코드가 충돌하거나 몇 사용자의 컴퓨터에서만 발생하는 heisenbugs를 추적하는 데 몇 주를 소비하게 될 것입니다. 물론 유용한 버그 리포트를 제출하는 방법을 알지 못함). – abarnert

+0

답장을 보내 주셔서 감사합니다. 내가 언급 한 함정이 내가 만날 수있는 합병증조차도 알지 못했습니다. 내가 더 조사해야 할 것 같아. – LISTERINE

관련 문제