협동 Python 에서 다 중 태 스 크 를 실현 하여 자원 을 최소 화 하 는 방식
협 정 은 Python 에서 다 중 임 무 를 실현 하 는 또 다른 방식 으로 스 레 드 보다 작 을 뿐 더 작은 실행 부 를 차지 합 니 다(필요 한 자원 으로 이해 합 니 다).
CPU 컨 텍스트 를 가지 고 있 기 때문에 왜 실행 장치 라 고 말 합 니까?이렇게 하면 적당 한 시기 에 우 리 는 하나의 협 정 을 다른 협 정 으로 전환 할 수 있다.이 과정 에서 CPU 컨 텍스트 를 저장 하거나 복원 하면 프로그램 이 실 행 될 수 있 습 니 다.
통속 적 인 이해:한 스 레 드 의 한 함수 에서 현재 함수 의 임시 변수 등 정 보 를 어디서 든 저장 한 다음 에 다른 함수 로 전환 하여 실행 할 수 있 습 니 다.함 수 를 호출 하 는 방식 으로 하 는 것 이 아니 라 전환 하 는 횟수 와 언제 원래 함수 로 전환 하 는 지 는 개발 자가 스스로 확인 할 수 있 습 니 다.
협정 과 노선 의 차이
다 중 작업 을 수행 할 때 스 레 드 전환 은 시스템 차원 에서 CPU 컨 텍스트 를 저장 하고 복원 하 는 것 만 간단 한 것 이 아 닙 니 다.
운영 체 제 는 프로그램 이 실행 하 는 효율 성 을 위해 모든 스 레 드 에 캐 시 Cache 등 데 이 터 를 가지 고 있 습 니 다.운영 체 제 는 이러한 데이터 의 복구 작업 을 도와 줄 수 있 기 때문에 스 레 드 의 전환 은 매우 성능 을 소모 합 니 다.
그러나 협 정의 전환 은 단순히 CPU 를 조작 하 는 문맥 일 뿐 1 초 에 수백 만 번 이상 시스템 을 전환 하 는 것 도 견 딜 수 있다.
이전에 우 리 는 yield 키 워드 를 말 한 적 이 있 는데,지금 은 그것 으로 다 중 임 무 를 실현 한다.
예:
import time
def task_1():
while True:
print("--1--")
time.sleep(0.5)
yield
def task_2():
while True:
print("--2--")
time.sleep(0.5)
yield
def main():
t1 = task_1()
t2 = task_2()
while True:
next(t1)
next(t2)
if __name__ == "__main__":
main()
실행 과정:먼저 t1 을 잠시 실행 시 키 고 t1 이 yield 를 만 났 을 때 main()순환 하 는 곳 으로 돌아 간 다음 t2 를 실행 합 니 다.yield 를 만 났 을 때 다시 t1 로 전환 하면 t1 과 t2 가 교체 되 어 운행 되 고 최종 적 으로 다 중 작업,협 정 을 실현 합 니 다.
실행 결과:
greenlet
다 중 작업 을 수행 하기 위해 Python 의 greenlet 모듈 을 패키지 하여 전환 작업 을 더욱 간단하게 합 니 다.
우선 greenlet 모듈 을 설치 해 야 합 니 다.
pip3 install greenlet
from greenlet import greenlet
import time
def test1():
while True:
print("---A--")
gr2.switch()
time.sleep(0.5)
def test2():
while True:
print("---B--")
gr1.switch()
time.sleep(0.5)
gr1 = greenlet(test1)
gr2 = greenlet(test2)
# gr1
gr1.switch()
실행 결과:우리 가 이전에 yield 로 실현 한 효과 와 마찬가지 로 greenlet 은 사실 yield 에 대해 간단 한 포장 을 했다.
greenlet 은 yield 보다 더 간단 하지만 우 리 는 앞으로 그것 을 사용 하지 않 을 것 이다.
위의 예 에서 지연 시간 은 0.5 초 이 고 지연 이 100 초 라면 프로그램 이 100 초 를 멈 추고 다른 수행 해 야 할 임무 가 있어 도 시스템 이 전환 되 지 않 으 며 이 100 초의 시간 은 이용 할 수 없다.
이 문 제 는 아래 에서 해결한다.
gevent
greenlet 은 협 정 을 실 현 했 지만 인공 전환 을 해 야 합 니 다.너무 귀 찮 지 않 습 니까?
Python 은 greenlet 보다 더 강력 하고 작업 을 자동 으로 전환 할 수 있 는 모듈 gevent 도 있 습 니 다.
gevent 는 greenlet 에 대한 재 포장 입 니 다.
그 원 리 는 greenlet 이 IO(input output 입 출력,예 를 들 어 네트워크,파일 작업 등)작업 을 만 났 을 때 예 를 들 어 네트워크 에 접근 하면 자동 으로 다른 greenlet 으로 전환 하고 IO 작업 이 끝 날 때 까지 기 다 렸 다가 적당 한 시기 에 전환 하여 계속 실행 하 는 것 이다.
IO 작업 이 매우 오래 걸 리 기 때문에 프로그램 이 대기 상태 에 있 습 니 다.gevent 가 우 리 를 위해 자동 으로 협 정 을 전환 하면 항상 greenlet 이 실 행 될 것 입 니 다.IO 를 기다 리 는 것 이 아니 라 greenlet 이 실 행 될 것 입 니 다.
우선 gevent 를 설치 해 야 합 니 다.
pip3 install gevent
예:
import gevent
def f(n):
for i in range(n):
print(gevent.getcurrent(), i)
g1 = gevent.spawn(f, 3)
g2 = gevent.spawn(f, 3)
g3 = gevent.spawn(f, 3)
g1.join()
g2.join()
g3.join()
실행 결과:세 개의 greenlet 은 교체 운행 이 아니 라 순서대로 운행 되 는 것 을 볼 수 있다.
이 는 gevent 가 다 중 태 스 크 의 효 과 를 실 현 했 는 지 판단 할 수 없 으 며,가장 좋 은 판단 상황 은 실행 결과 에 0,12 가 순서대로 나타 나 지 않 는 것 이다.
gevent 의 개념 에서 우 리 는 gevent 가 지연 되 었 을 때 자동 으로 작업 을 전환 할 것 이 라 고 언급 했다.
그러면 우 리 는 먼저 위의 예 에 시간 을 연장 한 다음 에 효 과 를 본다.
import gevent
import time
def f(n):
for i in range(n):
print(gevent.getcurrent(), i)
time.sleep(0.5)
g1 = gevent.spawn(f, 3)
g2 = gevent.spawn(f, 3)
g3 = gevent.spawn(f, 3)
g1.join()
g2.join()
g3.join()
실행 결과:지연 시간 을 추가 한 후 실행 결 과 는 변 하지 않 았 습 니 다.
사실 gevent 는 time.sleep()의 지연 이 아니 라 gevent.sleep()의 지연 을 원 합 니 다.
import gevent
def f(n):
for i in range(n):
print(gevent.getcurrent(), i)
gevent.sleep(0.5)
g1 = gevent.spawn(f, 3)
g2 = gevent.spawn(f, 3)
g3 = gevent.spawn(f, 3)
g1.join()
g2.join()
g3.join()
join 은 더 간단 한 표기 법 이 있다.
import time
import gevent
def f(n):
for i in range(n):
print(gevent.getcurrent(), i)
gevent.sleep(0.5)
gevent.joinall([
gevent.spawn(f, 3),
gevent.spawn(f, 3),
gevent.spawn(f, 3)
])
보통 뒤의 이런 표기 법 이다.실행 결과:
이제 야 다 중 태 스 크 의 효 과 를 실현 하 게 되 었 습 니 다.gevent 는 지연 되 었 을 때 자동 으로 다른 태 스 크 로 전환 합 니 다.
여 기 는 time 의 sleep 를 gevent 의 sleep 로 바 꿨 습 니 다.
그러면 네트워크 프로그램 이 있 으 면 네트워크 프로그램 에 도 많은 막힘 이 있 습 니 다.예 를 들 어 connect,recv,accept 등 은 gevent 의 대응 방법 으로 바 꿀 필요 가 없습니다.
이론 적 으로 말 하면 바 꿔 야 한다.gevent 를 사용 하려 면 모든 지연 작업 을 하고 이러한 함 수 를 막 으 며 모두 gevent 의 대응 방법 으로 바 꿔 야 합 니 다.
그 문제 가 있 습 니 다.만약 제 코드 가 10 만 줄 을 썼 다 면 어떻게 깨 뜨 릴 까요?
수 동 으로 수정 할 필요 가 없 는 방법 이 있 습 니까?있 습 니 다.패 치 를 하면 됩 니 다.
import time
import gevent
from gevent import monkey
#
# , gevent
monkey.patch_all()
def f(n):
for i in range(n):
print(gevent.getcurrent(), i)
time.sleep(0.5)
g1 = gevent.spawn(f, 3)
g2 = gevent.spawn(f, 3)
g3 = gevent.spawn(f, 3)
g1.join()
g2.join()
g3.join()
4.567914.코드 를 자동 으로 검사 하고 지연 되 는 모든 방법 을 gevent 의 방법 으로 자동 으로 바 꿉 니 다.실행 결과:
요약:
지연 되 는 시간 을 이용 해 다른 임 무 를 수행 하고 시간 을 모두 이용 하 는 것 이 협 정의 가장 큰 의미 다.
여기 서 협 정 Python 에서 다 중 태 스 크 자원 을 최소 화 하 는 방법 에 관 한 글 을 소개 합 니 다.더 많은 Python 다 중 태 스 크 자원 을 최소 화 하 는 방법 에 관 한 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 저 를 많이 지지 해 주세요!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Python의 None과 NULL의 차이점 상세 정보그래서 대상 = 속성 + 방법 (사실 방법도 하나의 속성, 데이터 속성과 구별되는 호출 가능한 속성 같은 속성과 방법을 가진 대상을 클래스, 즉 Classl로 분류할 수 있다.클래스는 하나의 청사진과 같아서 하나의 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.