Skip to content

Commit

Permalink
edit: add contents - 스케줄링 알고리즘
Browse files Browse the repository at this point in the history
  • Loading branch information
lja3723 committed Apr 22, 2024
1 parent 43183f7 commit c2209c8
Show file tree
Hide file tree
Showing 11 changed files with 231 additions and 46 deletions.
277 changes: 231 additions & 46 deletions _posts/Computer-Science/OS/2024-04-10-scheduling-algorithm.md
Original file line number Diff line number Diff line change
Expand Up @@ -248,13 +248,13 @@ _$\mathrm{T}n(k)$ = $n$번 스레드의 남은 실행 시간은 $k$라는 의미

### 4.2. 요약

| 평가 항목 | 내용 |
| :---------------: | -------------------------------------------- |
| 스케줄링 파라미터 | 스레드별 예상 실행 시간(남은 실행 시간) |
| 스케줄링 타입 | 비선점 스케줄링[^SJF-type] |
| 스레드 우선순위 | 없음 |
| 기아 | 발생 가능[^SJF-starve] |
| **성능 이슈** | 짧은 스레드 먼저 실행 → 평균 대기시간 최소화 |
| 평가 항목 | 내용 |
| :---------------: | ------------------------------------------------ |
| 스케줄링 파라미터 | 스레드별 예상 실행 시간(남은 실행 시간) |
| 스케줄링 타입 | 비선점 스케줄링[^SJF-type] |
| 스레드 우선순위 | 없음 |
| 기아 | 발생 가능[^SJF-starve] |
| **성능 이슈** | 짧은 스레드 먼저 실행 → **평균 대기시간 최소화** |

[^SJF-type]: **하지만 선점도 가능**한데, 이 경우는 **SRTF(Shortest Remaining Time First)** 알고리즘이 된다.
[^SJF-starve]: 지속적으로 짧은 스레드 도착 시, 긴 스레드는 언제 실행 기회 얻을 지 예측 불가능하다.
Expand Down Expand Up @@ -498,7 +498,7 @@ _$\mathrm{T}n(k)$ = $n$번 프로세스의 남은 실행 시간은 $k$라는 의
- **현재 스레드가 종료**되거나 **더 높은 순위의 스레드가 도착**할 때, 가장 높은 순위의 스레드 선택
- 도착하는 스레드는 **우선순위 순으로 큐에 삽입**된다.

### 7.1. 고정 순위 알고리즘
### 7.1. 고정 우선순위 알고리즘

- 한 번 우선순위를 부여받으면 종료때까지 **우선순위 고정**
- 단순히 구현 가능하지만, 시시각각 변하는 시스템 상황 반형 X → **효율성↓**
Expand All @@ -508,20 +508,72 @@ _$\mathrm{T}n(k)$ = $n$번 프로세스의 남은 실행 시간은 $k$라는 의
- 일정 시간마다 우선순위 변하여 **일정시간마다 우선순위 새로 계산/반영**
- 복잡하지만, 시스템 상황 반영해 **효율적인 운영** 가능

### 7.3. 예시
---

#### **예시**
{: data-toc-skip=''}

| 도착 순서 | 도착 시간 | 작업 시간 | 우선 순위 |
| --------- | --------- | --------- | --------- |
| P1 | 0 | 30 | 3 |
| P2 | 3 | 18 | 2 |
| P3 | 6 | 9 | 1 |

- 비선점 평균 대기 시간: 20
- 선점 평균 대기 시간:
#### **비선점인 경우**
{: data-toc-skip=''}

![]({{ img_path }}/7.3. 비선점.png){: width='450'}
_**직사각형 속 프로세스**: 실행중 프로세스<br>**수직선 밑 프로세스**: 그 프로세스 도착 시간_

![]({{ img_path }}/7.3. 비선점 큐.png){: width='400'}
_$\mathrm{T}n(k,p)$ = $n$번 프로세스 남은 실행 시간은 $k$이고, 우선순위는 $p$라는 의미_

##### **평균 대기 시간**
{: data-toc-skip=''}

- **P1**: $0$
- **P2**: $(39-3) = 36$
- **P3**: $(30-6) = 24$
- 평균 대기시간 = $(0 + 36 + 24)/3 = 20$

(내용 추가예정)
##### **평균 반환 시간**
{: data-toc-skip=''}

- **P1**: $0$
- **P2**: $(57-3) = 54$
- **P3**: $(39-6) = 33$
- 평균 반환시간 = $(0 + 54 + 33)/3 = 29$

---

### 7.4. 요약
#### **선점인 경우**
{: data-toc-skip=''}

![]({{ img_path }}/7.3. 선점.png){: width='450'}
_**직사각형 속 프로세스**: 실행중 프로세스<br>**수직선 밑 프로세스**: 그 프로세스 도착 시간_

![]({{ img_path }}/7.3. 선점 큐.png){: width='400'}
_$\mathrm{T}n(k,p)$ = $n$번 프로세스 남은 실행 시간은 $k$이고, 우선순위는 $p$라는 의미<br>**큐 맨 왼쪽 스레드**: 실행 중 스레드_

##### **평균 대기 시간**
{: data-toc-skip=''}

- **P1**: $(30-3) = 27$
- **P2**: $(15-6) = 9$
- **P3**: $0$
- 평균 대기시간 = $(27 + 9 + 0)/3 = 12$

##### **평균 반환 시간**
{: data-toc-skip=''}

- **P1**: $(57-0) = 57$
- **P2**: $(30-3) = 27$
- **P3**: $(15-6) = 9$
- 평균 반환시간 = $(57+27+9)/3= 31$

---

### 7.3. 요약

| 평가 항목 | 내용 |
| :---------------: | --------------------------------------------------------------- |
Expand All @@ -546,78 +598,211 @@ _$\mathrm{T}n(k)$ = $n$번 프로세스의 남은 실행 시간은 $k$라는 의
- **기아현상을 완화**하기 위해 만들어진 알고리즘
- SJF의 변형
- 서비스 받기 위해 기다린 시간과 CPU 사용시간 고려해 스케줄링 하는 방식
- **반드시 비선점이어야 함!**
- 선점인 경우 매 클럭마다 우선순위가 달라지므로, **매 클럭마다 문맥 교환이 일어날 수 있음!**

$$\mathrm{우선순위} = \frac{ \mathrm{대기시간} + \mathrm{CPU 사용시간} }{ \mathrm{CPU 사용시간} }$$
$$
\begin{aligned}
\mathrm{우선순위} &= \frac{ \mathrm{대기시간} + \mathrm{CPU 사용시간} }{ \mathrm{CPU 사용시간} } \\
&= 1 + \frac{ \mathrm{대기시간} }{ \mathrm{CPU 사용시간} }
\end{aligned}
$$

### 8.1. 예시

#### **Case 1**
{: data-toc-skip=''}

| 작업 | 대기 시간 | 서비스 시간 |
| ---- | --------- | ----------- |
| A | 5 | 20 |
| B | 40 | 20 |
| C | 15 | 45 |
| D | 20 | 20 |
| 작업 | 대기 시간 | 서비스 시간 | 우선순위 |
| ---- | --------- | ----------- | --------------------- |
| A | 5 | 20 | $(5 + 20)/20 = 1.25$ |
| B | 40 | 20 | $1 + (40/20) = 3$ |
| C | 15 | 45 | $1 + (15/45) = 1.333$ |
| D | 20 | 20 | $1 + (20/20) = 2$ |

(내용 추가예정)
- 정적 우선순위였다면 B - D - C - A 순으로 실행이 될 것임
- 동적 우선순위였다면
- B가 모두 실행되면 나머지 작업의 대기시간이 모두 +20이 될 것임
- 그러면 우선순위가 달라지므로 실행 순서가 달라질 수 있음

---

#### **Case 2**
{: data-toc-skip=''}

| 도착 순서 | 도착 시간 | 작업 시간 |
| --------- | --------- | --------- |
| P1 | 0 | 30 |
| P2 | 3 | 18 |
| P3 | 6 | 9 |
| 도착 순서 | 도착 시간 | 작업 시간 | P1 끝난 시점($t=30$)의 우선순위 |
| --------- | --------- | --------- | --------------------------------- |
| P1 | 0 | 30 | 고려 X |
| P2 | 3 | 18 | $1 + (27/18) = 2.5$ (대기시간 27) |
| P3 | 6 | 9 | $1 + (24/9) = 3.66$ (대기시간 24) |

- 따라서 $t=30$일 때 P3이 우선 실행되게 된다.

- 평균 대기 시간: 계산 필요
(내용 추가예정)
##### **평균 대기 시간**
{: data-toc-skip=''}

- **P1**: $0$
- **P2**: $27$
- **P3**: $24$
- 평균 대기시간 = $(0 + 27 + 24)/3 = 17$

---

### 8.2. 요약

| 평가 항목 | 내용 |
| :---------------: | ------------------------------------ |
| 스케줄링 파라미터 | 스레드 별 작업시간 + 대기시간 |
| 스케줄링 타입 | **비선점 스케줄링**[^HRN-type] |
| 스레드 우선순위 | **있음** |
| 기아 | 발생 낮음[^HRN-starve] |
| 성능 이슈 | 대기시간 긴 스레드일 수록 우선순위 ↑ |
| 평가 항목 | 내용 |
| :---------------: | ------------------------------------- |
| 스케줄링 파라미터 | 스레드 별 작업시간 + 대기시간 |
| 스케줄링 타입 | **반드시 비선점 스케줄링**[^HRN-type] |
| 스레드 우선순위 | **있음** |
| 기아 | 발생 낮음[^HRN-starve] |
| 성능 이슈 | 대기시간 긴 스레드일 수록 우선순위 ↑ |

[^HRN-type]: 선점일 경우 핑퐁핑퐁핑퐁
[^HRN-type]: 선점일 경우 매 클럭마다 서로 작업을 가져가는 핑퐁 현상이 발생할 수 있다.
[^HRN-starve]: 알고리즘에 의해 거의 발생하지 않지만, 여전히 공평하다고는 말하기 어려움



## 9. MLQ(Multi-level Queue)

(내용 추가예정)
- 스레드를 n개의 우선순위 레벨로 구분한 후, 우선순위 레벨 높은 스레드들을 **우선적으로 처리**
- 고정된 **n개의 큐 사용**, 각 큐에 **고정 우선순위** 할당
- 스레드들의 우선순위도 n개의 레벨로 분류
- **각 큐****나름대로의 기법**으로 스케줄링
- 스레드 도착 시 **우선순위에 따라 해당 레벨 큐에 삽입**
- 다른 큐로 이동할 수 없음
- 가장 높은 순위 큐가 빌 때, 그 다음 순위의 큐에서 스케줄링함

![]({{ img_path }}/9. MLQ.png)
_MLQ 알고리즘의 예시_



## 10. MLFQ(Multi-level Feedback Queue)

(내용 추가예정)
- **기아를 없애기 위해** 여러 레벨의 큐 사이 간 스레드 이동이 가능하도록 설계됨
- 고정된 **n개의 큐 사용**, 큐마다 서로 다른 레벨 스케줄링 알고리즘
- 큐마다 스레드가 머무를 수 있는 큐 타임슬라이스가 있음
- **낮은 레벨 큐**일수록 **더 긴 타임 슬라이스**

---

- 스레드는 도착 시 **최상위 레벨의 큐**에 삽입
- 가장 높은 레벨의 큐에서 스레드 선택. 비어 있는 경우 그 아래의 큐에서 스레드 선택
- 스레드의 CPU-burst가 **큐 타임 슬라이스를 초과**하면 강제로 **아래 큐로 이동**시킴
- 스레드가 **자발적으로 중단한 경우**, **현재 큐 끝**에 삽입
- 스레드가 I/O로 실행이 중단된 경우, **I/O가 끝나면 동일한 레벨 큐 끝에 삽입**
- **큐에 있는 시간이 오래**되면 기아를 막기 위해 **하나 위 레벨 큐로 이동**

![]({{ img_path }}/10. MLFQ.png)
_MLFQ 알고리즘의 예시_

---

#### **예시**
{: data-toc-skip=''}

- 3개의 레벨 큐
- 3개의 스레드

![]({{ img_path }}/10. MLFQ 예시.png)
_MLFQ 알고리즘의 예시_

- 평균 대기 시간: $(5+13+13)/3 = 10.3$

### 10.1. 요약

| 평가 항목 | 내용 |
| :---------------: | ------------------------------------- |
| 스케줄링 파라미터 | 스레드 별 작업시간 + 대기시간 |
| 스케줄링 타입 | **반드시 비선점 스케줄링**[^HRN-type] |
| 스레드 우선순위 | **있음** |
| 기아 | 발생 낮음[^HRN-starve] |
| 성능 이슈 | 대기시간 긴 스레드일 수록 우선순위 ↑ |




## 11. 멀티코어 CPU 스케줄링
## 11. 참고

![]({{ img_path }}/11. 멀티코어 CPU 스케줄링.png){: width='650'}
- 각 스케줄링 알고리즘은 서로 섞여서 사용될 수 있음
- RR + SJF
- MLQ + FCFS
- **MLQ + RR**
- ...

- 꼭 Queue만 사용하는 것은 아님
- 리눅스 CFS(Completely Fair Scheduler): Red-black tree 구조 활용

- 우선순위마다 다른 스케줄링dl 사용되기도 함
- 리눅스의 경우(숫자가 낮을 수록 높은 우선순위)
- Priority 0-99: Real-time process, static priority (RR 사용)
- Priority 100-139: Ordinary process, dynaic priority (CFS 사용)



## 12. 멀티코어 CPU 스케줄링

![]({{ img_path }}/12. 멀티코어 CPU 스케줄링.png){: width='650'}
_멀티코어 CPU 스케줄링의 예_

### 11.1. 문제점
### 12.1. 문제점

- 스케줄링을 통해 프로세스는 지정된 순서에 따라 CPU를 들락날락함
- 그런데 멀티코어에서는 **스케줄링이 여러 CPU에 걸쳐 발생**하게 될 수 있음
- **서로 다른 코어**에 걸쳐서 Context Switching이 발생한다면?

- **C1, 컨텍스트 스위칭 오버헤드 증가 문제**
- 이전에 실행된 적 없는 코어에 스레드가 배치될 때
- ex) Core1 → Core3
- 캐시에 새로운 스레드의 코드와 데이터로 채워지는 긴 경과 시간
- **C2, 코어별 부하 불균형 문제**
- 스레드를 무작위로 코어에 할당시, 코어마다 처리할 스레드 수의 불균형 발생
- ex) P1 → Core1, P2 → Core1, P3 -> Core1, P4 → Core1, ...
- Core2, Core3은?

### 12.2. 해결책

#### 12.2.1 코어간 Context switching 문제

**CPU 친화성(CPU affinity)** 부여로 해결한다.

- a.k.a., 코어 친화성(Core affinity), CPU 피닝(pinning), 캐시 친화성
- **스레드를 동일한 코어에서만 실행**하도록 스케줄링
- **코어 당 스레드 큐** 사용

- **윈도우 예시**

![12.2.1. 해결책]({{ img_path }}/12.2.1. 해결책.png){: width='500'}
_윈도우에서의 코어 친화성 설정_

- **리눅스 예시**
- `taskset -c <논리 CPU번호> <명령어>`
- 확인: `sar -P 0 1 1`

![12.2.1. 해결책 리눅스]({{ img_path }}/12.2.1. 해결책 리눅스.png){: width='500'}
_리눅스에서의 코어 친화성 설정_


#### 12.2.2 코어별 부하 불균형 문제

**부하 균등화 기법**으로 해결한다.

(내용 추가예정)
- 코어 사용량 감시 **스레드가 작업을 재할당(migration)**하여 부하 분산
- **Push migration**
- 짧거나 빈 큐 가진 코어에 다른 큐 스레드를 옮겨놓는 기법
- **Pull migration**
- 코어가 처리할 스레드가 없게 되면, 다른 코어의 스레드 큐에서 자신이 큐에 가져와 실행시키는 기법

### 11.2. 해결책

(내용 추가 예정)

## 11.3. 생각해볼 거리
## 13. 생각해볼 거리

(내용 추가 예정)
- 하나의 프로세스에 일어나는 작업을 여러 코어/스레드에 걸쳐서 하려면?
- 만약 공유데이터에 두 함수가 아무 생각 없이 임의의 순서로 접근하면
- 공유데이터가 훼손되는 문제 발생
- 공유데이터에 다수의 스레드가 접근시에는 서로 합을 맞추는 것이 필요함
- 그래서 다음시간에 배우는 것 → **동기화(Synchronazation)**



Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit c2209c8

Please sign in to comment.