컴퓨터/운영체제

[OS] Thread (1)

xeskin 2020. 4. 16. 15:51
반응형

스레드가 왜 필요한가?

- 하나의 프로세스에서 병렬 실행을 위해

- 동일한 환경에서 서로 다른 일을 동시적으로 처리할 수 있도록

동일한 환경 = 프로세스, 프로그램 코드, 데이터, 메모리 공간, 커널 데이터 구조 등을 말한다.

 

예) 웹 브라우저

스레드를 지원하지 않는 싱글코어 프로세서에서는 유저 인터페이스를 처리할 때는 렌더링이 안되고, 렌더링을 하는 동안에는 유저 인터페이스를 처리할 수가 없다. 즉, 내가 어떤 화면을 클릭해서 렌더링을 하는 동안에는 다른 모든 것 정지된 상태이고, 처리가 되지 않는다. 다른 것도 실행되게 만들어주려면 실행 흐름을 여러개 만들어주어야 한다.

 

스레드는 경량 프로세스라고도 불린다.

스레드는 스레드별로 스레드 아이디, 프로그램 카운터, 레지스터셋, 스택을 갖고 있다.

 

멀티 스레드 프로세스는 코두, 데이터, 파일을 모든 스레드가 공유한다. 그리고 각 스레드별로 레지스터값, 스택, 프로그램 카운터를 따로 갖고 있다. 운영체제는 프로세스의 정보를 PCB에 저장하는데 스레드의 구현은 어떻게 할 수 있을까? 우선, PCB가 어떻게 이뤄져있는지 알아보자.

 

프로세스는 PCB라는 블록으로 표현되는데, 이는 프로그램 코드, 프로세스 스테이트, 프로세스 아이디, 부모 프로세스, execution state를 갖고 있다. 여기서 execution state에는 프로그램 카운터, 레지스터 스테이트, 메모리 컨텐츠를 갖고 있는데 이를 따로 관리해주면 된다.

 

스레드를 왜 사용하나?

- 프로세스를 생성하는 것보다 스레드를 생성하는 것이 오버헤드가 적다. 프로세스를 생성하기 위해서는 이를 실행할 환경을 구축해줘야 하는데, 메모리 공간, 프로그램 코드와 같은 것을 만들어줘야한다. 스레드는 환경을 구축하지 않고 execution state만 하나씩 더 만드는 것이기 때문에 오버헤드가 적다.

- 리소스 사용 측면에서 효율적이다. 동일한 태스크를 병렬적으로 처리할 때 프로세스를 생성하는 것은 낭비다.

- 데이터 공유가 쉽다. IPC가 필요하지 않다. 스레드간에는 환경을 공유하기 때문이다.

 

스레드의 장점

- 응답성을 높일 수 있다. 한 부분이 블락돼도, 다른 파트를 실행하면 되니까.

- 파일, 메모리와 같은 리소스를 공유할 수 있다.

- 경제적이다. 프로세스는 생성, 종료할 때마다 메모리, 리소스 할당, 컨텍스트 스위치가 오버헤드다.

- 멀티코어 아키텍쳐를 효율적으로 사용할 수 있다.

 

스레드 vs 프로세스

스레드를 생성하는 것이 프로세스를 생성하는 것보다 10배 이상 빠르다.

스레드는 힙 영역을 공유한다. 스택은 스레드마다 따로 있다. 예를 들어, 스레드1,2,3은 각자 스택1,2,3을 갖고 있다.

스레드를 구현하는 방법: PCB를 두개로 나눈다.

- 스레드 관련 부분: 프로세서 스테이트, TCB

- 프로세스 스페시픽한 부분: 주소 공간, 운영체제의 리소스

- TCB에 대한 주소값을 PCB에 저장한다.

 

리눅스에서는 thread_struct를 TCB의 구조로, task_struct를 PCB의 구조로 사용함. 프로세서별로 TCB는 다르다. 왜냐하면 구조가 다르기 때문에.. 레지스터 종류가 다르다.

멀티 스레드를 지원하는 환경에서의 context switch

: TCB가 context switch의 단위가 된다.

- 레디큐, 웨잇큐와 같은 것이 TCB에 대한 포인터가 된다.

- context switch시에, CPU의 상태를 TCB에 복사하거나 읽어온다.

- 동일한 프로세스의 스레드간 context switch는 주소 공간을 바꿀 필요가 없다. 즉, 캐시를 날릴 필요가 없다.

- 서로 다른 프로세스간의 context switch는 가상 메모리 주소 공간을 바꿔줘야한다. 캐시에 감긴 정보를 다 날려줘야 하는데, 다른 주소 공간이기 때문에 캐시에 들어간 건 사용하면 안된다.

- context switch를 할 때 오버헤드가 일어나는 주원인은 캐시에 있는 걸 지우는 것이다. 지워버리면 메인 메모리에서 다시 읽어와야 하는데, 캐시는 상당히 빠른데 비해 메인 메모리는 느리기 때문이다.

 

멀티코어 프로그래밍 (multi-core programming)

- 멀티 프로세서: 하나의 시스템에 cpu가 여러개 있는 것을 말한다.

- 멀티코어: CPU칩에 코어가 여러개 있는 것을 말한다.

- 동시성 (Concurrency): 여러 개의 스레드가 있을 때, 태스크가 조금씩 실행되도록 만드는 것을 말한다.

- 병렬성 (Parallelism): 실제로 여러개의 태스크를 동시에 실행하는 것을 말한다.

> Concurrent하지만, parallel하지 않은 경우가 있음

- Concurrent execution은 싱글 코어 프로세서의 성능 향상에 기여할까?

> I/O burst, CPU burst 측면에서 생각해보면, 성능 향상이 있다. I/O 요청을 하는 동안에 다른 태스크를 실행하면 되니까.

 

멀티코어 프로그래밍이 어려운 점 다섯가지

- 멀티 코어를 사용하려면, 이를 위한 스케쥴링 알고리즘이 필요하다.

- 프로그램을 멀티 스레드로 구현할 필요가 있다.

1. 어떤 부분이 독립적이고 병렬적으로 수행할 수 있는지 분석해야한다.

2. 밸런스를 맞춰줘야 한다. 각 스레드의 실행 시간을 맞춰줘야한다.

3. 데이터 분배. 두개의 태스크가 각 코어에서 실행되는데, 이 태스크들은 어레이에 저장돼있는 값을 갖고 연산을 수행한다. 데이터가 10개 있다고 할 때, 각 코어에 5/5로 데이터로 나눠주는 것이 이상적인데, 1/9와 같이 나눠주면 하나의 코어에서 실행되는 것은 오래 걸리고, 다른 것은 빨리 끝날 것이다.

4. 데이터의 디펜던시와 싱크를 맞춰줘야 한다. 이 수준에 따라 병렬화 수준이 갈릴 것이다.

5. 테스팅과 디버깅이 어렵다. 싱글 스레드로 구현할 땐ㄴ 시퀀셜하게 실행되서 코드의 실행 순서를 예측하기 쉬운데, 두개의 태스크로 나눠서 동시에 실행될 때는 예측이 어렵다.

 

병렬성 (Parallelism)

- 데이터 병렬성 (Data Parallelism): 어떤 동일한 함수를 실행할 때, 데이터를 나눠 서로 다른 스레드에서 실행 하는 걸 생각해보면 된다. 모든 스레드는 동일한 함수를 실핸하는데, 데이터가 다른 경우.

싱글코어: 0에서부터 n-1까지 더한다.

듀얼코어: 코어1은 0에서부터 n/2-1까지, 코어2는 n/2부터 n-1까지 병렬적으로 더한다.

- 태스크 병렬성 (Task Parallelism): 동일한 데이터를 사용하여, 여러 함수를 다른 코어에서 실행하는 경우를 말한다. 하나의 코어에서는 평균값늘 내고, ,다른 코어에서는 다 덧셈을 하는 거.

반응형

'컴퓨터 > 운영체제' 카테고리의 다른 글

[OS] Thread (3)  (0) 2020.04.23
[OS] Thread (2)  (0) 2020.04.16
[OS] Inter Process Communication (IPC)  (1) 2020.04.15
[OS] Context Switch와 레지스터 셋의 관계  (0) 2020.04.15
[OS] Interrupt  (0) 2020.04.03