컴퓨터 파워

매일 공부(ML)·2021년 11월 10일
0

CS 

목록 보기
23/33

멀티태스킹

동시성(Concurrency)

  • 정의: 하나의 processor가 여러 가지 task를 동시 수행하는 개념

  • 특징: task를 전환해서 효율적으로 여러 개의 task를 동시에 수행하는 것 같음

동기 vs 비동기

  • 동기: 한 작업이 끝난 후에 다른 작업 수행가능(대기 시간엔 대기함), 일이 순차적으로 진행이 되어 요청과 요청에 대한 응답이 연속적 실행.

  • 비동기: 대기 시간에 다른 일을 처리함, 일이 비순차적으로 진행이 되어 요청과 요쳥에 대한 응답이 연속적이지 않아서 특정 코드의 연산이 끝날때 까지 코드의 실행을 멈추지 않고 다음 코드 먼저 실행하는 콜백함수로 연결

병렬성

  • 정의: 유사한 task를 여러 processor 동시에 수행

  • 특징:

    • processor의 개수만큼 퍼포먼스 수행

    • 동시성이 요구할 때 병렬성의 효율 극대화.

    • 여러 개의 프로세스가 1개의 task를 여러 개의 subtask쪼개어 수행

I/O Bound vs CPU Bound

  • Bound: 어떤 일을 바로 하지 못하고 대기해야 하는 일

  • I/O Bound: 입출력에서 데이터 처리 시간이 소요

  • CPU Bound: 복잡한 수식 계산이나 그래픽 작업과 같은 엄청난 계산 필요 시 사용

Process(프로세스)

  • 정의: 프로그램 구동하여 프로그램 자체와 상태가 메모리 상에서 실행되는 작업 단위

  • 특징:

    • 스케줄링의 대상이 되는 작업(task)

    • 운영체제의 커널에서 시스템 자원(CPU,메모리,디스크)및 자료구조 이용

    • 프로그램을 구동하여 프로그램 자체와 상태가 메모리 상에서 실행되는 작업 단위

    • 여러 프로세스를 사용하는 것을 멀티 프로세싱이라고 한다

    • 프로세스 관리는 os의 중요한 부분이다

    • 자신만의 전용 메모리 공간(Heap)가진다.

  • 커널

  • 생성(create): 프로세스가 생성되는 중이다

    • 실행(running): 프로세스가 cpu를 차지하여 명령어들이 실행

    • 준비(ready): 프로세스가 CPU를 사용하진 않지만 언제든 사용 가능한 상태. 우선순위 순으로 CPU할당됨

    • 대기(waiting): 보류라고 부른다. 입출력 완료, 시그널 수긴 등 어떤 사건을 기다리는 상태

    • 종료(terminated): 프로세스의 실행이 종료됨

  • 프로세스의 상태전이

    	- 디스패치(dispatch)

    : 준비 상태에서 실행 상태로 바뀌는 것

    dispatch (processname) : ready -> running

    • 보류(block)

      : 허가된 시간을 다 쓰기 전에 입출력 동작이 필요한 경우 CPU반납하여 보류 상태로 감

      block (processname) : running -> blocked

    • 깨움(wakeup)

      : 보류 상태에서 준비 상태로 넘어가는 과정

      wakeup (processname) : blocked -> ready

    • 시간제한(timeout)

      : 프로세스가 프로세서를 독점하지 못하게 일정시간동안만 점유하도록 함

      : timeout (processname) : running ->ready

스레드(Thread)

  • 정의: 프로세스 내에서 실행되는 흐름의 단위

  • 특징: 한 프로세스 안의 스레드들이 메모리 공간을 공유하지만 다른 프로세스랑은 안함

프로파일링(Profiling)

  • 정의: 코드에서 시스템의 어느 부분이 느린지 혹은 어디서 RAM을 사용하는지 확인 기법

  • 특징:

    	- 코드의 병목을 찾아 성능 측정
    • 패키지 : profile모듈(파이썬), cProfile모듈(C언어), line_profiler 패키지 이용

Scale Up vs Scale Out

  1. Scale Up

  • 정의: 한 대의 컴퓨터 성능을 최적화 시키기

  • 특징:

- 단일 서버(하드웨어)의 성능 증가시켜 더 많은 요청 처리

- CPU, 메모리, 하드디스크 등을 업그레이드 혹은 증가시킴

- 별도의 서버 추가하지 않기에 데이터 정합성 이슈에 자유로움

- 별도의 소프트웨어 라이선스 추가 비용 발생 않음

- 구현이 어렵지 않음
  • 단점:

    • 하나의 서버 장비에는 cpu, 메몰, 디스크의 수 제한이 있다.

      - 한정된 자원을 초과하여 성능을 증가하기 위해선 서버 자체 변경
    • 일정 수준이 넘어가는 순간 성능 증가 폭이 미미해짐

    • 성능 증가 대비 업그레이드 비용이 굉장히 비쌈

    • 서버 한 대가 모든 클라이언트의 트래픽을 감당해야 하기에 과부화가능.

  1. Scale Out

  • 정의: 여러 대의 컴퓨터를 한 대처럼 사용하는 것

  • 특징:

    	- 동일 사양의 새로운 서버를 추가하여 성능 증가
    • 서버 증설로 인해 여러 대의 서버가 트래픽을 나누어 갖고 이를 처리함
    • 가용성이 높다
    • 필요에 따라 서버 추가 감소가 가능하여 확장에 유연함
    • 로드 밸런싱 구현해야함
    • 트래픽 증가 시, 적절히 분담하여 처리하게해야 병목현상을 줄임
    • 병행적 처리가 필요한 곳에서 필요
  • 단점:

    	- 서버가 늘어날때 마다 소프트웨어 라이선스 비용이 증가한다.(오픈소스 활용으로 비용 줄이기)
    • 여러 대의 서버로 하나의 서비스를 사용하려면 데이터 불일치가 잠재적으로 발생

    • 정합성 이슈에서 자유로울 수 없다.

멀티스레드

  1. Code로 구현

*기본코드

class Delivery:
	def run(self):
		print("delivery")

class RetriveDish:
	def run(self):
		print("Retriving Dish")

work1 = Delivery()
work2 = RetriveDish()

def main():
	work1.run()
	work2.run()

if __name__ == '__main__':
    main()

*멀티스레드

# threading 모듈을 import
# 클래스에 Thread를 상속

from threading import *

class Delivery(Thread):
	def run(self):
		print("delivery")

class RetriveDish(Thread):
	def run(self):
		print("Retriving Dish")

work1 = Delivery()
work2 = RetriveDish()

def main():
	work1.run()
	work2.run()

if __name__ == '__main__':
    main()

*스레드 생성 확인


# 함수 이름을 출력하면 함수 객체 확인
from threading import *

class Delivery:
    def run(self):
        print("delivering")

work1 = Delivery()
print(work1.run)

class Delivery(Thread):
    def run(self):
        print("delivering")

work2 = Delivery()
print(work2.run)
  1. 스레드 생성

2-1. 스레드 생성 방식

  • threading 모듈의 Thread 클래스 상속 받아 구현

  • 인스턴스화 시킨다

    i) Thread클래스에 인자로 target과 args값 넣기

    ii) args에 넣어 준 파라미터는 스레드 함수의 인자로 넘어감

    t = Thread(target=함수이름, args=())

  • Thread클래스에는 start(), join()같은 동작관련 메소드가 있고 실행 함수 정의 후 start() 통해 스레드 실행

# 수행코드
from threading import *
from time import sleep

Stopped = False

def worker(work, sleep_sec):    # 일꾼 스레드입니다.
    while not Stopped:          # 그만 하라고 할때까지
        print('do ', work)      # 시키는 일을 하고
        sleep(sleep_sec)        # 잠깐 쉽니다.
    print('retired..')          # 언젠가 이 굴레를 벗어나면, 은퇴할 때가 오겠지요?
        
t = Thread(target=worker, args=('Overwork', 3))    # 일꾼 스레드를 하나 생성합니다. 열심히 일하고 3초간 쉽니다.
t.start()    # 일꾼, 이제 일을 해야지? 😈

#종료 코드
# 이 코드 블럭을 실행하기 전까지는 일꾼 스레드는 종료하지 않습니다. 
Stopped = True    # 일꾼 일 그만하라고 세팅해 줍시다. 
t.join()          # 일꾼 스레드가 종료할때까지 기다립니다. 
print('worker is gone.')
  1. 프로세스 생성
  • Process인스턴스를 만든 후 target와 args 파라미터에 각각 함수 이름과 인자 전달
import multiprocessing as mp

def delivery():
    print('delivering...')

p = mp.Process(target=delivery, args=())
p.start()
  1. 프로세스 사용
  • 프로세스 동작관련 메소드: start(), join(), terminate()
p = mp.Process(target=delivery, args=())
p.start() # 프로세스 시작
p.join() # 실제 종료까지 기다림 (필요시에만 사용)
p.terminate() # 프로세스 종료

풀 사용하기

  • 정의: 스레드나 프로세스들로 가득 찬 풀장

  • 방식:

    	1. Queue 사용하여 직접 만들기
    1. concurrent.futures

      : 라이브러리의 ThreadPoolExecutor, ProcessPoolExecutor클래스 이용

  • concurrent.futures모듈이란?

  • 기능:

  • Executor 객체

    *서브클래스

    • ThreadPoolExecutor
    • ProcessPoolExecutor

    *메소드

    • submit()
    • map()
    • shutdown()
  • ThreadPoolExecutor 객체

    • Executor 객체 이용 시, 스레드 생성,시작,조인 같은 작업할 때 with방법이용
      with ThreadPoolExecutor() as executor:
      future = executor.submit(함수이름, 인자)

*Delivery클래스 이용

from concurrent.futures import ThreadPoolExecutor

class Delivery:
    def run(self):
        print("delivering")
w = Delivery()

with ThreadPoolExecutor() as executor:
    future = executor.submit(w.run)
  • ProcessPoolExecutor 객체
  • Future 객체
  • multiprocessing.Pool

*multiprocessing.Pool.map을 이용하여 여러 개의 프로세스에 특정 함수 매핑하여 병렬 처리

from multiprocessing import Pool
from os import getpid

def double(i): # pool을 통해 각각 다른 pid를 가진 프로세스 위에 multiprocess실행
    print("I'm processing ", getpid())    # pool 안에서 이 메소드가 실행될 때 pid를 확인해 봅시다.
    return i * 2

with Pool() as pool:
      result = pool.map(double, [1, 2, 3, 4, 5])
      print(result)
profile
성장을 도울 아카이빙 블로그

0개의 댓글