문제

파이썬에서 다중 스레드 애플리케이션을 작성하는 데 사용되는 모듈은 무엇입니까? 나는 언어와 또한 기본 동시성 메커니즘을 알고 있습니다. 스택이없는 파이썬, 그러나 각각의 강점과 약점은 무엇입니까?

도움이 되었습니까?

해결책

복잡성을 높이기 위해 :

사용 스레딩 모듈

장점 :

  • 자체 스레드에서 기능 (실제로 호출 가능)을 실행하는 것은 정말 쉽습니다.
  • 데이터 공유는 쉽지 않은 경우 (잠금은 쉽지 않습니다 :) 적어도 단순합니다.

단점 :

  • 말한 바와 같이 Juergen에 의해 Python 스레드는 실제로 통역사에서 동시에 상태에 액세스 할 수 없습니다 (큰 잠금 장치가 하나 있습니다. 글로벌 통역사 잠금.) 실제로 의미하는 것은 스레드가 I/O 바운드 작업 (네트워킹, 디스크 작성 등)에 유용하지만 동시 계산에 전혀 유용하지 않다는 것입니다.

사용 다중 프로세싱 기준 치수

간단한 유스 케이스에서 이것은 사용과 똑같이 보입니다. threading 각 작업이 자체 프로세스에서 실행되는 것을 제외하고는 자체 스레드가 아닙니다. (거의 말 그대로 : 당신이 가져 가면 엘리의 예, 교체 threading ~와 함께 multiprocessing, Thread, 와 함께 Process, 그리고 Queue (모듈) multiprocessing.Queue, 그것은 잘 달릴 것입니다.)

장점 :

  • 모든 작업에 대한 실제 동시성 (글로벌 통역사 잠금 없음).
  • 여러 프로세서로의 스케일은 여러 개로 스케일링 할 수도 있습니다. 기계.

단점 :

  • 프로세스는 스레드보다 느립니다.
  • 프로세스 간 데이터 공유는 스레드보다 까다 롭습니다.
  • 메모리는 암시 적으로 공유되지 않습니다. 당신은 그것을 명시 적으로 공유해야하거나 변수를 피클하고 앞뒤로 보내야합니다. 이것은 더 안전하지만 더 어렵습니다. (점점 더 중요하다면 파이썬 개발자들은이 방향으로 사람들을 밀고있는 것 같습니다.)

다음과 같은 이벤트 모델을 사용하십시오 꼬인

장점 :

  • 당신은 언제 실행되는지에 대한 우선 순위에 대한 매우 잘 제어됩니다.

단점 :

  • 좋은 라이브러리를 사용하더라도 비동기 프로그래밍은 일반적으로 스레드 프로그래밍보다 어렵습니다. 무슨 일이 일어나고 있는지 이해하고 실제로 일어나는 일을 디버깅하는 측면에서 어렵습니다.

~ 안에 모두 사례는 이미 멀티 태스킹과 관련된 많은 문제, 특히 작업 간 데이터를 공유하는 방법에 대한 까다로운 문제를 이미 이해하고 있다고 가정합니다. 어떤 이유로 든 자물쇠와 조건을 언제 어떻게 사용하는지 모른다면 그부터 시작해야합니다. 멀티 태스킹 코드는 미묘함과 gotchas로 가득 차 있으며 시작하기 전에 개념을 잘 이해하는 것이 가장 좋습니다.

다른 팁

당신은 이미 "가짜 스레드"에서 외부 프레임 워크에 이르기까지 상당한 다양한 답변을 얻었지만 아무도 언급하지 않았습니다. Queue.Queue -Cpython 스레딩의 "비밀 소스".

확장하려면 : 순수한 파이썬 CPU-Heave 처리를 겹칠 필요가없는 한 (이 경우 필요한 경우 multiprocessing - 그러나 그것은 그 자체로 제공됩니다 Queue 구현도, 필요한주의 사항을 사용하여 제가주고있는 일반적인 조언을 적용 할 수 있습니다 .-), Python의 내장. threading 할 것입니다 ...하지만 사용하면 훨씬 더 잘할 것입니다. 조언합니다, 예를 들어, 다음과 같이.

"잊어 버린"공유 메모리, 아마도 스레딩 대 멀티 프로세싱의 주요 플러스 - 잘 작동하지 않으며, 확장되지 않고, 결코없고, 결코 의지하지 않습니다. 한 번 설정 한 데이터 구조에 대해서만 공유 메모리를 사용하십시오. ~ 전에 당신은 하위 스레드를 스폰하고 나중에는 결코 바뀌지 않았습니다. 다른 모든 것을 위해 하나의 해당 리소스를 담당하고 해당 스레드와 통신합니다. Queue.

자물쇠로 보호하기 위해 일반적으로 생각하는 모든 자원에 특수 스레드를 바르십시오 : 변이 가능한 데이터 구조 또는 응집력있는 그룹, 외부 프로세스 (DB, XMLRPC 서버 등), 외부 파일 등 등의 연결 . 그런 종류의 전용 리소스가 없거나 필요한 범용 작업을 위해 작은 스레드 풀을 얻으십시오. ~하지 않다 필요할 때 나사산 스폰 또는 스레드 스위치 오버 헤드가 당신을 압도합니다.

두 스레드 사이의 통신은 항상 경유됩니다 Queue.Queue -메시지 전달의 형태, 멀티 프로세싱을위한 유일한 제정신 재단 (유망하지만 Haskell을 제외한 생산에 가치가없는 구현을 알고있는 트랜잭션 메모리 외에도).

단일 리소스 (또는 소규모 응집력있는 리소스 세트)를 관리하는 각 전용 스레드는 특정 대기열 .queue 인스턴스의 요청을 듣습니다. 수영장의 스레드는 단일 공유 대기열에서 대기합니다. 습관 이것에 실패합니다).

일부 대기열 (공유 또는 전용)의 요청을 대기 해야하는 스레드는 결과를 기다리지 않고 계속 진행합니다. 결국 요청 대기열에 대한 결과 또는 확인이 필요한 스레드는 방금 만든 큐 인스턴스와 함께 쌍 (요청, 수신 Queceue)과 결국 응답이나 확인이 없어서는 안될 때 (대기) ) 그들의 수신 큐에서. 실제 응답 또는 확인뿐만 아니라 오류 응답을받을 준비가되어 있는지 확인하십시오 (Twisted 's deferredS는 이러한 종류의 구조화 된 반응을 구성하는 데 능숙합니다. BTW!).

또한 큐를 사용하여 한 스레드에서 사용할 수 있지만 한 번에 여러 스레드에서 공유 할 수있는 자원의 "공원"인스턴스를 사용하여 한 번에 공유 할 수 있습니다 (일부 DBAPI 컴포넌트와의 DB 연결, 다른 DBAPI 구성 요소 등) - 이렇게하면 완화 할 수 있습니다. 더 많은 풀링 (공유 대기열에서 가져 오는 풀 스레드)에 유리한 전용 스레드 요구 사항은 대기열 자원이 필요한 요청을 제공하는 풀 스레드는 적절한 대기열에서 해당 리소스를 얻을 수 있습니다. 필요한 경우 대기 등).

Twisted는 실제로 연기 덕분 에이 Minuet (또는 Square Dance)를 구성하는 좋은 방법입니다. 진정으로 보증되지만 대부분의 일을하는 동안 일반적으로 단일 이벤트 중심 스레드에서 스레드 가치가있는 것으로 간주됩니다.

그러나 나는 Twisted가 모든 사람을위한 것이 아니라는 것을 알고 있습니다. "전용 또는 풀 리소스, Wazoo를 사용하고, 자물쇠가 필요한 것도하지 않거나 Guido 금지, 세마포어 또는 조건과 같은 동기화 절차"접근법이 가능합니다. Async 이벤트 중심 방법론을 중심으로 머리를 감을 수없는 경우에도 여전히 사용되며, 내가 우연히 발견 한 다른 널리 적용 가능한 스레딩 접근 방식보다 더 많은 신뢰성과 성능을 제공 할 것입니다.

그것은 당신이하려는 일에 달려 있지만, 나는 단지 threading 표준 라이브러리의 모듈은 기능을 취하고 별도의 스레드에서 실행하기 쉽기 때문에 실제로 실행할 수 있기 때문입니다.

from threading import Thread

def f():
    ...

def g(arg1, arg2, arg3=None):
    ....

Thread(target=f).start()
Thread(target=g, args=[5, 6], kwargs={"arg3": 12}).start()

등등. 나는 종종 Queue 기준 치수

from Queue import Queue
from threading import Thread

q = Queue()
def consumer():
    while True:
        print sum(q.get())

def producer(data_source):
    for line in data_source:
        q.put( map(int, line.split()) )

Thread(target=producer, args=[SOME_INPUT_FILE_OR_SOMETHING]).start()
for i in range(10):
    Thread(target=consumer).start()

카마 엘리아 많은 의사 소통 프로세스가있는 응용 프로그램을 구축하기위한 파이썬 프레임 워크입니다.

(원천: kamaelia.org) Kamaelia- 동시성은 유용하고 재미있었습니다

Kamaelia에서는 시스템을 구축합니다 서로 대화하는 간단한 구성 요소. 이것은 개발 속도를 가속화하고 대규모 유지 보수를 지원하며 또한 귀하를 의미합니다. 자연스럽게 동시 소프트웨어를 구축하십시오. 접근 할 수 있도록 의도 된 것입니다 어느 초보자를 포함한 개발자. 그것은 또한 그것을 재미있게 만듭니다 :)

어떤 종류의 시스템? 네트워크 서버, 클라이언트, 데스크톱 응용 프로그램, 피그 게임 기반 게임, 트랜스 코드 시스템 및 파이프 라인, 디지털 TV 시스템, 스팸 근거기, 교육 도구 등 :)

다음은 Pycon 2009의 비디오입니다. Kamaelia를 비교하여 시작합니다. 꼬인 그리고 병렬 파이썬 그리고 카마 엘리아의 시연에 손을 낳습니다.

Kamaelia와의 쉬운 동시성 - 1 부 (59:08)
Kamaelia와의 쉬운 동시성 - 2 부 (18:15)

Kamaelia와 관련하여 위의 답변은 실제로 여기서 이점을 다루지 않습니다. Kamaelia의 접근 방식은 단일 시스템에서 실행, 생성기 및 프로세스를 동시성을위한 단일 시스템에서 처리하기 위해 완벽하지 않은 통합 인터페이스를 제공합니다.

기본적으로 그것은받은 편지함과 외출물이있는 러닝 물건의 은유를 제공합니다. 메시지를 소장으로 보내고 함께 연결하면 메시지가 외출에서받은 편지함으로 흘러갑니다. 이 은유/API는 발전기, 스레드 또는 프로세스를 사용하거나 다른 시스템과 대화하든 동일하게 유지됩니다.

"완벽하지 않은"부분은 아직받은 편지함과 항문에 대해 구문 설탕이 추가되지 않았기 때문입니다 (논의 중이지만) 시스템의 안전성/유용성에 중점을 둡니다.

위의 베어 스레딩을 사용하여 생산자 소비자 예제를 취하면 이것은 Kamaelia에서 다음과 같습니다.

Pipeline(Producer(), Consumer() )

이 예에서는 이들이 스레드 구성 요소인지 여부는 중요하지 않습니다. 유일한 차이점은 사용 관점에서의 유일한 차이점은 구성 요소의베이스 클래스입니다. Generator 구성 요소는 OS.PIPES를 사용하여 Queue.queues 및 프로세스를 사용하여 목록, 나사산 구성 요소를 사용하여 통신합니다.

그러나이 접근법의 이유는 버그를 디버깅하기가 어렵게 만들기 때문입니다. 스레딩 또는 공유 메모리 동시성에서 귀하가 직면 한 가장 큰 문제는 실수로 공유 데이터 업데이트가 깨졌습니다. 메시지 전달을 사용하여 제거합니다 하나 버그 클래스.

베어 스레딩과 잠금 장치를 사용하는 경우 일반적으로 코드를 작성할 때 실수를하지 않을 것이라는 가정에서 작업하고 있습니다. 우리 모두가 그것에 대해 열망하는 동안, 일어날 일은 매우 드 rare니다. 잠금 동작을 한 곳에 마무리하면 상황이 잘못 될 수있는 곳을 단순화합니다. (컨텍스트 핸들러가 도움이되지만 컨텍스트 핸들러 이외의 우발적 업데이트에 도움이되지 않음)

분명히 모든 코드 조각이 메시지 전달 및 공유 스타일로 쓸 수있는 것은 아니기 때문에 Kamaelia는 간단한 소프트웨어 트랜잭션 메모리 (STM)를 가지고있는 이유입니다. 일부 변수를 확인하고 업데이트하고 다시 커밋하십시오. 충돌을 받으면 헹구고 반복합니다.

관련 링크 :

어쨌든, 나는 그것이 유용한 대답이되기를 바랍니다. FWIW, Kamaelia의 설정에 대한 핵심 이유는 꼬리가 개를 흔들지 않고 동시성을 더 안전하고 파이썬 시스템에서 더 쉽게 사용하는 것입니다. (즉, 구성 요소의 큰 양동이

다른 Kamaelia 답변이 왜 수정되었는지 이해할 수 있습니다. 왜냐하면 나에게도 대답보다 광고처럼 보이기 때문입니다. Kamaelia의 저자로서 열정을 보는 것은 반갑습니다. 그러나 이것이 좀 더 관련성있는 내용이 포함되기를 바랍니다 :-)

그리고 이것이 제가 말하는 방식입니다.이 답변은 정의에 의해 편견이 있다는 경고를 받아들이지만, Kamaelia의 목표는 IMO 모범 사례를 시도하고 포장하는 것입니다. 몇 가지 시스템을 사용해 보시고 어느 것이 당신에게 도움이되는지 보는 것이 좋습니다. (또한 이것이 스택 오버플로에 부적절하다면 죄송합니다 - 저는이 포럼을 처음 사용합니다 :-)

스레드를 전혀 사용해야한다면 스택리스 파이썬의 마이크로 스레드 (작업 목적)를 사용합니다.

전체 온라인 게임 (Massivly Multiplayer)은 Stackless 및 Multithreading 원칙을 중심으로 구축됩니다. 원본은 게임의 거대한 멀티 플레이어 속성에 속도가 느려지 기 때문입니다.

Cpython의 실은 널리 낙담합니다. 한 가지 이유는 GIL (글로벌 통역사 잠금 장치)이 실행의 많은 부분에 대한 스레딩을 직렬화하기 때문입니다. 저의 경험은 이런 식으로 빠른 응용 프로그램을 만드는 것이 정말 어렵다는 것입니다. 스레딩이 모두 느려지는 예제 코딩 - 하나의 코어가 있습니다 (그러나 많은 입력 대기로 인해 성능 향상이 가능해졌습니다).

cpython을 사용하면 가능하면 별도의 프로세스를 사용하십시오.

정말로 손을 더럽 히고 싶다면 시도해 볼 수 있습니다. 발전기를 사용하여 가짜 코 루틴에. 아마도 관련 작업 측면에서 가장 효율적이지는 않지만 코 루틴은 당신에게 매우 훌륭한 제어를 제공합니다. 협력적인 다른 곳에서 찾을 수있는 선제적인 멀티 태스킹보다는 멀티 태스킹.

당신이 찾을 수있는 한 가지 장점은 대체로 협동 된 멀티 태스킹을 사용할 때 자물쇠 나 뮤 테스가 필요하지 않지만 "스레드"사이의 거의 0 인 전환 속도라는 것입니다. 물론, Stackless Python은 그것에 대해서도 매우 좋다고합니다. 그리고 그렇지 않은 경우 Erlang이 있습니다 가지다 파이썬이되기 위해.

아마도 협동 된 멀티 태스킹에서 가장 큰 단점은 I/O 차단에 대한 일반적인 해결 방법 부족 일 것입니다. 그리고 가짜 코 루틴에서는 스레드 내에서 스택의 최상위 레벨 이외의 "스레드"를 전환 할 수없는 문제를 만날 수 있습니다.

가짜 코 루틴으로 약간 복잡한 응용 프로그램을 만든 후에는 OS 수준에서 프로세스 스케줄링에 들어가는 작업에 정말로 감사하기 시작할 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top