협동 Python 에서 다 중 태 스 크 를 실현 하여 자원 을 최소 화 하 는 방식

8166 단어 Python다 중 임무
협 정영어 이름 Corontine.
협 정 은 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()
실행 결과:
0
1
2
0
1
2
0
1
2
세 개의 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()
실행 결과:
0
1
2
0
1
2
0
1
2
지연 시간 을 추가 한 후 실행 결 과 는 변 하지 않 았 습 니 다.
사실 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)
])
보통 뒤의 이런 표기 법 이다.
실행 결과:
0
0
0
1
1
1
2
2
2
이제 야 다 중 태 스 크 의 효 과 를 실현 하 게 되 었 습 니 다.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 의 방법 으로 자동 으로 바 꿉 니 다.
실행 결과:
0
0
0
1
1
1
2
2
2
요약:
지연 되 는 시간 을 이용 해 다른 임 무 를 수행 하고 시간 을 모두 이용 하 는 것 이 협 정의 가장 큰 의미 다.
여기 서 협 정 Python 에서 다 중 태 스 크 자원 을 최소 화 하 는 방법 에 관 한 글 을 소개 합 니 다.더 많은 Python 다 중 태 스 크 자원 을 최소 화 하 는 방법 에 관 한 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 저 를 많이 지지 해 주세요!

좋은 웹페이지 즐겨찾기