Post

외전-프로세스와 쓰레드

외전-프로세스와 쓰레드

지난 이야기

저번에는 파이썬 multiprocessing 라이브러리의 process와 pool 기능을 알아보았다.
그래서 이번에는 파이썬 쓰레딩 사용법을 설명해야 하는데…
사실 글을 쓰려고 준비를 하다보니 설명해야 할 배경지식이 너무 많다. 원리를 말하려자니 핵심 용어들을 설명할 컴퓨터 이론쪽 지식이 필요하기 때문이다.
따라서 이번에는 외전격으로, 컴퓨터 과학에서 의미하는 프로세스와 쓰레드, 둘의 차이, 멀티프로세싱과 멀티쓰레딩을 이야기하겠다.
혹시 본인이 컴퓨터 공학을 전공했거나 운영체제 수업을 들었으면 넘겨라. 들어도 좋고

요약

  • 병렬 처리에는 크게 멀티프로세싱과 쓰레딩이 있다.
  • 멀티프로세싱은 하나의 작업을 하는 프로세스를 여러 개 만들어 동시에 수행하는 기법이다.
  • 쓰레딩은 하나의 프로세스 내에서 여러 작업을 동시에 수행하는 기법이다.
  • 멀티프로세싱은 데이타를 공유하지 않지만, 쓰레딩은 일부 데이타를 공유한다. 이 때문에 멀티프로세싱과 쓰레딩은 일장일단이 있다.

용어 정리

비슷하면서도 다른 단어가 너무 많아, 잠깐 용어 정리가 필요하겠다.

  • 프로세서: 우리가 흔히 CPU라고 말하는 것
  • 코어: 프로세서 안에 존재하는 물리적인 프로세서
  • 작업: 프로세스가 처리하는 일.(함수,메소드 등등)
  • 프로세스: 실행되고 있는 프로그램
  • 쓰레드: 프로세스 안에 존재하는 작업 단위

쓰레딩

  • 지난 시간에 배운 멀티프로세싱프로세스를 여러 개 만들어, 시간을 단축시키는 기술이다.
    • 서로 다른 프로세스를 실행시킬 때는 process, 하나의 프로세스를 여러 번 실행해야 할 때는 pool을 사용하면 편리하다는 것도 배웠다.
  • 반면 이번 시간에 배울 쓰레딩멀티프로세싱의 하위 개념으로, 하나의 프로세스 내에서 여러 ‘쓰레드’를 생성해 여러 작업을 실행할 때 쓰이는 기술이다.

프로세스와 쓰레드

  • 프로세스는 실행 중인 프로그램이다.
  • 쓰레드프로세스 안에 존재하는 작업 단위이다.
  • 프로세스가 실행할 작업은 쓰레드에서 처리된다.
  • 프로세스는 논리적으로 분리되어 있으며 서로 간 소통하기 위해서는 특수한 규칙이 필요하다.
  • 반면 쓰레드는 작업 실행에 필요한 메모리를 제외한 모든 저장 공간을 공유한다. 따라서 쓰레드 간 소통이 상대적으로 자유롭다.

프로세스와 쓰레드의 저장공간

  • 백문이 불여일견. 그림으로 설명하자.
    th1-img1
    • 멀티프로세싱의 구조이다. 각 프로세스가 독립적인 저장 공간을 할당받는다.
      • 운영체제 강의를 들으면 알겠지만, 프로세서가 사용하는 저장공간에는 레지스터, 캐쉬, 메모리(RAM)이 있다. 메모리<캐쉬<레지스터 순으로="" 속도가="" 빨라="" 메모리-="">캐쉬->레지스터 순으로 데이타를 가져온다.(계층 구조)
      • 그리고 프로그램이 잡아먹는 메모리는 크게 네 종류로 나뉘어진다.
        • 프로그램 코드가 들어가는 Code
        • 프로그램 전역변수가 들어가는 Data
        • 사용자가 임의로 사용하는 Heap
        • 프로그램이 자동으로 사용하는 Stack
      • Code와 Data는 프로그램 실행시 그 크기가 고정되어 있어서 정적 데이터, Heap과 Stack은 크기가 유동적으로 변하므로 동적 데이터라고 한다.
        • Heap의 사례로는 C++의 new, amalloc, delete 같이 직접 메모리 용량을 할당하고 없애는 것을 의미한다.
        • Stack의 대표적인 예는 함수 호출의 지역변수,인자,리턴값 등등이 있다.
          함수가 실행되면 함수 내 변수나 인자, 리턴값이 들어갈 Stack을 할당받고 끝나면 없앤다.
        • 참고로 Heap과 Stack는 같은 메모리 용량을 공유한다. 즉 Heap이 커질수록 Stack이 작아지고 바이스버사.
    • 잡설이 길었다. 아무튼 프로세싱의 특징은 각 프로세서가 사용하는 메모리 공간이 독립적이라는 것만 기억하자.
  • 반대로 쓰레딩은 하나의 프로세스 내에서 작동하기 때문에 여러 쓰레드 작업이 하나의 메모리를 공유한다. th1-img2
    • 프로세스 하나에 쓰레드가 여러 개 존재한다.
    • 쓰레드는 작업, 즉 함수를 실행하므로 스택은 각자 따로 가진다.
    • 따라서 나머지 메모리(코드/힙/데이타)는 공유한다.

쓰레딩의 장점?

  • 위에서 쓰레딩은 하나의 프로세스 안에서 이루어지므로 자원공간을 공유한다는 특성을 설명했다. 쓰레딩의 장점은 여기에 있다.
  • 장점을 설명하기 전에, 문맥 교환(context switching)을 설명해야 하기에 우선 말하겠다.
    • 문맥 교환은 쉽게 말해서 프로세스 간 소통하는 방식이다.
    • 프로세서 하나는 하나의 프로세스만 실행할 수 있기에, 중간에 다른 프로세스를 실행하려면 지금까지의 프로세스 상태(레지스터/캐쉬/메모리에 있는 값 등)을 따로 저장해놓은 뒤 저장공간을 초기화해야 한다.
    • 이제 다른 프로세스가 실행되면서 해당 저장공간을 활용하고, 마찬가지로 이전 프로세스 작업을 해야할 때 현재 상태를 저장한 뒤 이전 프로세스에 저장공간을 넘겨준다.
    • 이전 프로세스는 기존에 저장되었던 상태를 저장공간에 불러오고, 작업을 계속하고 다른 프로세스 요청이 오면 무한반복…
    • 이 과정은 운영체제가 알아서 해준다.
  • 위에서 말했듯이, 쓰레드들은 일부 저장 공간을 공유한다. 반면 프로세스들은 저장 공간이 독립되어 있다.
    • 따라서 프로세스를 생성하는 것보다 쓰레드를 생성하는 것이 시간과 자원을 덜 먹는다.
  • 또한 프로세스는 문맥 교환시 모든 저장공간을 저장->초기화->불러오기 해야 하는데, 쓰레드는 일부 저장공간을 공유하므로 이 과정에서 걸리는 자원1이 줄어든다.

쓰레딩의 단점

  • 쓰레딩의 단점도 마찬가지로 하나의 프로세스 내에서 작동한다는 것에 기인한다.
  • 우선 쓰레드 중 하나가 뻗어버리면 프로세스 전체가 뻗어버린다. 이것은 일종의 안전장치인데, 요즘 유행하는 코로나 비루스에 비유해 보자.
    • 프로세스는 하나의 집이다. 만약 이 집에서 감염자가 발생해도 다른 집은 영향을 받지 않는다.
    • 쓰레드는 집에 사는 가족들이다. 만약 가족 중 한명이라도 감염되면 다른 가족들은 즉시 일상생활을 중단하고 격리되어야 한다.
  • 또한 다중 코어 프로세서 환경에서는 임계 영역 문제가 발생할 수 있다.
    • 다중 코어 프로세서에서 쓰레딩을 실행하면 운영체제가 각 코어에 쓰레드를 할당해준다. 이 경우에는 각 쓰레드가 동시에 실행될 수 있다.
    • 두 개의 쓰레드가 존재하는데, 1번 쓰레드는 전역변수 값을 바꾸는, 2번 쓰레드는 전역변수 값을 읽어들이는 작업을 한다고 가정하자.
    • 만약 두 쓰레드가 동시에 실행된다면, 전역변수 값을 읽는 쓰레드가 변경되기 전의 값을 읽어버리는 문제가 발생할 수 있다.
    • 이 문제를 해결하는 대표적인 방법으로는 lock이 있다.
      • lock은 이러한 공유값에 접근하는 부분2이 있으면 그 부분 전에서 쓰레드 실행을 멈추고, 다른 쓰레드를 실행한다.
      • 즉 2번 쓰레드의 전역변수 값을 읽는 부분에 lock을 걸어 1번 쓰레드를 먼저 실행하게 한 뒤, 2번 쓰레드의 나머지 부분을 실행하는 것이다.
      • 다만 이것도 문제가 있어, 요즘 운영체제는 더 유식한 방법인 뮤텍스세마포어로 해결한다. 얘들은 꽤 복잡하므로 시간 나면 다루겠다…
  1. 유식한 말로 오버헤드라고 부른다. ↩︎

  2. 유식한 말로 임계 영역이라고 부른다. ↩︎

This post is licensed under CC BY 4.0 by the author.