스레드는 Python에서 어떻게 작동하며 일반적인 Python- 스레딩 관련 함정은 무엇입니까?
나는 스레드가 파이썬에서 어떻게 작동하는지에 대해 머리를 감싸려고 노력해 왔는데, 스레드가 어떻게 작동하는지에 대한 좋은 정보를 찾기가 어렵습니다. 링크 나 뭔가 빠졌을 수도 있지만 공식 문서가 주제에 대해 그다지 철저하지 않은 것 같고 좋은 글을 찾을 수 없었습니다.
내가 알 수 있듯이 한 번에 하나의 스레드 만 실행될 수 있으며 활성 스레드는 10 개의 명령어 정도마다 전환됩니까?
좋은 설명이 어디에 있습니까? 아니면 설명 할 수 있습니까? Python에서 스레드를 사용하는 동안 발생하는 일반적인 문제를 인식하는 것도 매우 좋습니다.
예, GIL (Global Interpreter Lock) 때문에 한 번에 하나의 스레드 만 실행할 수 있습니다. 이에 대한 몇 가지 통찰력이있는 링크는 다음과 같습니다.
- http://www.artima.com/weblogs/viewpost.jsp?thread=214235
- http://smoothspan.wordpress.com/2007/09/14/guido-is-right-to-leave-the-gil-in-python-not-for-multicore-but-for-utility-computing/
마지막 링크에서 흥미로운 인용문 :
그게 무슨 뜻인지 설명하겠습니다. 스레드는 동일한 가상 머신 내에서 실행되므로 동일한 물리적 머신에서 실행됩니다. 프로세스는 동일한 물리적 시스템 또는 다른 물리적 시스템에서 실행될 수 있습니다. 스레드를 중심으로 애플리케이션을 설계하는 경우 여러 컴퓨터에 액세스하기 위해 아무 작업도하지 않았습니다. 따라서 단일 머신에있는 코어 수만큼 확장 할 수 있지만 (시간이 지남에 따라 상당 수) 실제로 웹 스케일에 도달하려면 어쨌든 여러 머신 문제를 해결해야합니다.
멀티 코어를 사용하려는 경우 pyprocessing 은 실제 병렬화를 수행하기 위해 프로세스 기반 API를 정의합니다. PEP는 또한 몇 가지 흥미로운 벤치 마크가 포함되어 있습니다.
Python은 스레드하기가 매우 쉬운 언어이지만주의 사항이 있습니다. 알아야 할 가장 큰 것은 Global Interpreter Lock입니다. 이렇게하면 하나의 스레드 만 인터프리터에 액세스 할 수 있습니다. 이것은 두 가지를 의미합니다. 1) 파이썬에서 lock 문을 사용하는 경우는 거의 없으며 2) 다중 프로세서 시스템을 활용하려면 별도의 프로세스를 사용해야합니다. 편집 : 또한 GIL을 둘러보고 싶다면 C / C ++에 일부 코드를 넣을 수 있음을 지적해야합니다.
따라서 스레드를 사용하려는 이유를 다시 고려해야합니다. 듀얼 코어 아키텍처를 활용하기 위해 앱을 병렬화하려면 앱을 여러 프로세스로 분할하는 것을 고려해야합니다.
응답 성을 향상 시키려면 스레드 사용을 고려해야합니다. 그러나 다른 대안, 즉 microthreading이 있습니다. 살펴 봐야 할 몇 가지 프레임 워크도 있습니다.
다음은 기본 스레딩 샘플입니다. 20 개의 스레드를 생성합니다. 각 스레드는 스레드 번호를 출력합니다. 그것을 실행하고 그들이 인쇄하는 순서를 관찰하십시오.
import threading
class Foo (threading.Thread):
def __init__(self,x):
self.__x = x
threading.Thread.__init__(self)
def run (self):
print str(self.__x)
for x in xrange(20):
Foo(x).start()
당신이 암시했듯이 파이썬 스레드는 시간 분할을 통해 구현됩니다. 이것이 그들이 "병렬"효과를 얻는 방법입니다.
내 예제에서 내 Foo 클래스는 스레드를 확장 한 다음 스레드에서 실행 run
하려는 코드가있는 메서드 를 구현합니다 . 스레드를 시작하려면 start()
자동으로 run
메서드를 호출하는 스레드 개체에서 호출합니다 .
물론 이것은 기본에 불과합니다. 결국 스레드 동기화 및 메시지 전달을위한 세마포어, 뮤텍스 및 잠금에 대해 배우고 싶을 것입니다.
개별 작업자가 I / O 바인딩 작업을 수행하는 경우 Python에서 스레드를 사용합니다. 머신의 여러 코어에서 확장하려는 경우 Python에 적합한 IPC 프레임 워크를 찾 거나 다른 언어를 선택하십시오.
참고 : 내가 언급하는 곳 thread
은 명시 적으로 언급 할 때까지 특별히 파이썬 스레드를 의미합니다 .
스레드는 C/C++
백그라운드 에서 온 경우 Python에서 약간 다르게 작동합니다 . 파이썬에서는 주어진 시간에 하나의 스레드 만 실행 상태에있을 수 있습니다. 즉, 설계 상 스레드가 여러 코어에서 병렬로 실행될 수 없기 때문에 파이썬의 스레드는 여러 처리 코어의 힘을 진정으로 활용할 수 없습니다.
파이썬의 메모리 관리는 스레드로부터 안전하지 않기 때문에 각 스레드는 파이썬 인터프리터의 데이터 구조에 대한 배타적 액세스가 필요합니다.이 배타적 액세스는 (전역 인터프리터 잠금) 이라는 메커니즘에 의해 획득됩니다 .GIL
Why does python use GIL?
여러 스레드가 인터프리터 상태에 동시에 액세스하여 인터프리터 상태를 손상시키는 것을 방지하기 위해.
The idea is whenever a thread is being executed (even if it's the main thread), a GIL is acquired and after some predefined interval of time the GIL is released by the current thread and reacquired by some other thread( if any).
Why not simply remove GIL?
It is not that its impossible to remove GIL, its just that in prcoess of doing so we end up putting mutiple locks inside interpreter in order to serialize access, which makes even a single threaded application less performant.
so the cost of removing GIL is paid off by reduced performance of a single threaded application, which is never desired.
So when does thread switching occurs in python?
Thread switch occurs when GIL is released.So when is GIL Released? There are two scenarios to take into consideration.
If a Thread is doing CPU Bound operations(Ex image processing).
In Older versions of python , Thread switching used to occur after a fixed no of python instructions.It was by default set to 100
.It turned out that its not a very good policy to decide when switching should occur since the time spent executing a single instruction can very wildly from millisecond to even a second.Therefore releasing GIL after every 100
instructions regardless of the time they take to execute is a poor policy.
In new versions instead of using instruction count as a metric to switch thread , a configurable time interval is used. The default switch interval is 5 milliseconds.you can get the current switch interval using sys.getswitchinterval()
. This can be altered using sys.setswitchinterval()
If a Thread is doing some IO Bound Operations(Ex filesystem access or
network IO)
GIL is release whenever the thread is waiting for some for IO operation to get completed.
Which thread to switch to next?
The interpreter doesn’t have its own scheduler.which thread becomes scheduled at the end of the interval is the operating system’s decision. .
One easy solution to the GIL is the multiprocessing module. It can be used as a drop in replacement to the threading module but uses multiple Interpreter processes instead of threads. Because of this there is a little more overhead than plain threading for simple things but it gives you the advantage of real parallelization if you need it. It also easily scales to multiple physical machines.
If you need truly large scale parallelization than I would look further but if you just want to scale to all the cores of one computer or a few different ones without all the work that would go into implementing a more comprehensive framework, than this is for you.
Try to remember that the GIL is set to poll around every so often in order to do show the appearance of multiple tasks. This setting can be fine tuned, but I offer the suggestion that there should be work that the threads are doing or lots of context switches are going to cause problems.
I would go so far as to suggest multiple parents on processors and try to keep like jobs on the same core(s).
'code' 카테고리의 다른 글
root 사용자를 제외하고 'test'@ 'localhost'사용자 (암호 사용 : YES)에 대한 액세스가 거부되었습니다. (0) | 2020.09.19 |
---|---|
const void 란 무엇입니까? (0) | 2020.09.19 |
linq의 let 키워드가 into 키워드보다 낫습니까? (0) | 2020.09.19 |
루비 1.8.6 (each_char)에서 문자열의 각 문자에 대해 반복 (0) | 2020.09.19 |
논리 연산자의 서면 버전 (0) | 2020.09.19 |