python advanced (2)

Haks.·2024년 12월 15일
0

Study

목록 보기
11/65
  • Thread 란? : 프로세스 내에서 실행되는 하나의 작업 단위
  • 하나의 프로세스엔 메인 쓰레드가 있으며, 여러 개의 추가 스레드를 생성하여 병렬 작업 수행 가능
  • GIL(Global Interpreter Lock) : 파이썬의 경우, 한 번에 한 스레드만 python 바이트 코드로 실행 가능, Python에서 멀티스레딩은 주로 I/O 작업에 유리하며, CPU 집약적인 작업(CPU-Bound Tasks)에서는 효과가 떨어질 수 있습니다.

📌 geneartor,iterator


next(), yield, __iter__

  • next()
class splitter :
	def __init__(self,text) :
    	self._idx = 0
        self._text = text.split(' ')
    
    def __next__(self) :
    	print('called __next__)
        try :
        	word = self.text[self._idx]
        except IndexError :
        	raise StopIteration('Stopped Itteration.')
        self._idx += 1
        return word
    def __repr__(self) :
    	return 'word split(%s)' % (self._text)

word_split = splitter('do today what you can')
print(word_split) # word split([do, today, what, you, can])
print(next(word_split) # called __next__ do
print(next(word_split) # called __next__ today 
  • yield (제너레이터), __iter__
class splitter() :
	def __init__(self,text) :
    	self._text = text.split(' ')
    def __iter__(self) :
    	for word in self._text :
        	yield word # 제너레이터
    def __repr__(self) :
    	return 'word split(%s)' % (self._text)

word_gene = splitter('do today')
wt = iter(wg) # 이터함수를 따로 설정

print(wt) # genertor object ...
print(word_gene) # word split(['do','today'])
print(next(wt)) # do
print(next(wt)) # today

📌 병행성, 병렬성


병행성 : 한컴퓨터가 여러 일을 동시에 수행 -> 단일 프로그램 안에서 여러일을 쉽게 수행
병렬성 : 여러 컴퓨터가 여러 작업을 동시에 수행 -> 속도

def generator1() :
	print('strat')
    yield 'A point' # 첫 next 사용시 여기서 대기
    print('continue')
    yield 'B point' # 두번째 next 시 여기까지 출력 a 부터
    print('end')
temp = generator1()
print(next(temp)) # start, A point
print(next(temp)) # continue, B point
print(next(temp)) # end , StopIteration 에러 발생
temp2 = [x * 3 for x in generator_1()] # ['A point A point A point ', 'B point B point B point '] yield 부분이 x 로 들어감
temp3 = (x * 3 for x in generator_1()) # <generator object <genexpr> at 0x11fa1f440>

for i in temp3:
    print(i) # Apoint,Bpoint 3회 반복되고 출력 start부터 end 까지

📌 코루틴, yield


함수를 실행 중간에 멈췄다가 다시 실행을 재개 할 수 있는 함수
반드시 시작(next) 하고 사용해야함

  • 코루틴 : 단일(싱글) 스레드, 스텍을 기반으로 동작하는 비동기 작업
  • 쓰레드 : os 관리, CPU 코어에서 실시간 ,시분할 비동기 작업 -> 멀티쓰레드
  • yield : 메인과 서브가 상호작용 : 코루텐 제어, 상태, 양방향 전송 # send 루틴을 통해
  • 서브루틴 : 메인루틴 호출 -> 서브루틴에서 수행 (흐름제어)
  • 코루틴 : 루틴 실행 중지 -> 동시성 프로그래밍
  • 코루틴 : 쓰레드에 비해 오버헤드 감소
  • 스레드 : 싱글스레드 -> 멀티스레드 -> 복잡 -> 공유되는 자원 -> 교착 상태 발생 가능성, 컨텍스트 스위칭 비용 발생, 자원 소비 가능성 증가 오히려 싱글스레드가 빠를수도 있음
    * def -> async, yield -> await : python 3.5 이상부터 사용 가능
  • 코루틴
# 서브 루틴 (만들기)
def coroutine1() :
	print('coroutine start.')
    i = yield # 중요!!!
    print('coroutine received : {}'.format(i))
# 메인 루틴 
cr1 = coroutine1()
print(cr1, type(cr1)) # generator object...,<class 'generator'>
# yield 지점까지 서브루틴 수행
next(cr1) # coroutine start
# 전달한 값이 없기에 none 출력
next(cr1) # coroutine received : None + 당연히 stopiteration 발생

# 위를 주석처리하고 첫 start 상태에서
# 값 전송 send()
cr1.send(1) 
next(cr1) # coroutine received : 1 + 당연히 stopiteration 발생
# start 를 하지 않은 상태에서 바로 send 값을 주면 yield 에 도달하지 않은 상태기에 오류발생, 타입에러

# 상태값 출력 가능
# from inspect import getgeneratorstate
# GEN_CREATED : 처음 대기 상태
# GEN_RUNNING : 실행 상태
# GEN_SUSPENDED : yield 대기 상태
# GEN_CLOSED : 실행 완료 상태

from inspect import getgeneratorstate # 인세펙터 모듈 사용

	def coroutine2(x) :
    	print('started : 'x)
        y = yield x  # 1 포인트
        print('received : ',y)
        z = yield x + y # x+y 값 반환 보려면 반환시켜야댐 # 2 포인트
        print('received : ',z)
cr3 = coroutine2(10)

print(getgeneratorstate(cr3)) # 현재상태 : GEN_CREATED 출력
next(cr3)
print(getgeneratorstate(cr3)) # started : 10 ,GEN_SUSPENDED, 현재 1번포인트 대기
# 2번째 포인트의 yield 반환 x+y 값을 쓰고싶다면?
result = cr3.send(100) # 보내느 값을 반환 받는 변수를 찾아줘야한다!!!
# send 에대한 received 100 먼저 출력후 
print(result) # 110 출력됨
# 3. 두 번째 send 호출
try:
    result = cr3.send(200)     # 세 번째 yield에서 반환된 값 (없으므로 종료)
    print(f'Returned by yield: {result}')
except StopIteration:
    print('Coroutine finished')  # 코루틴 종료 처리
print(getgeneratorstate(cr3))  # GEN_CLOSED

# stopiteration 자동처리
# 중첩 코루틴

def generator1() :
	for x in 'AB' :
    	yield x
    for y in range(1,4) :
    	yield y 

t1 = generator1()
print(next(t1)) # A
print(next(t1)) # B
print(next(t1)) # 1
print(next(t1)) # 2
print(next(t1)) # 3
t2 = generator1() # 이미 다소진했기에 전부 다보려면 새로 출력
print(list(t2)) # ['A,'B','1','2','3'] # 

def generator2() : # 위와 똑같은 제너레이터 이다
	yield from 'AB'
    yield from range(1,4) 

---

📌 병렬성 (futures)


  • 비동기 작업 실행 (<-> 동기 : 순차적으로 실행)
  • 지연시간 CPU 및 리소스 낭비 방지 -> Network(file) I/O 관련 작업 -> 동시성 활용 권장
  • concurrent.Futures : 잘 만들어 져 있느 모듈 사용
  • ThreadPoolExecutor vs ProcessPoolExecutor
    • 멀티스레드 // 멀티프로세스
    • 사례 : I/O 바운드 작업 (파일 읽기/쓰기, 네트워킹 등) // CPU 바운드 작업 (복잡한 계산, 데이터 처리)
    • GIL의 영향 : GIL(Global Interpreter Lock)에 영향 받음 // GIL 해제
    • 성능 : 스레드 간 메모리 공유로 메모리 효율적 // 프로세스 간 메모리 분리로 약간 비효율적
import time
from cocurrent import futures
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor, wait, as_completed


work_list =[1000,10000,100000,1000000]
# 누적 합계 함수 제네레이터 활용
def sum_generator(n) :
	return sum(n for n in range(1,n+1))

def main () :
	worker = min(10,len(work_list))
    start = time.time()
    # wait
    # 결과 
    # ProcessPoolExecutor, ThreadPoolExecutor (순차,병렬)
    with futures.ThreadPoolExecutor() as executor :
    	# map -> 작업 순서 유지, 즉시 실행
        result = executor.map(sum_generator,work_list)
        # wait 결과 출력
        result = wait(futures_list, timeout=7) # 시간을 정할수 있고 제어 할 수있다.
    end = time.time() - start
    
    msg = '\n Result -> {} Time : {:.2f}s'
    
    # as completed
    print(msg.format(list(result),end))
    as_completed 결과 출력 # 먼저 끝나는것 부터 하나씩 출력된다 
       for future in as_completed(futures_list):
           result = future.result()
           done = future.done()
           cancelled = future.cancelled
            
           # future 결과 확인
           print('Future Result : {}, Done : {}'.format(result, done))
           print('Future Cancelled : {}'.format(cancelled))
if __name__ == '__main__' :
	main()

## from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor, wait, as_completed


0개의 댓글

관련 채용 정보