봉황대 in CS

[Chapter 4. 스레드] 암묵적 스레딩 (스레드 풀, OpenMP, GCD) 본문

Computer Science & Engineering/Operating System

[Chapter 4. 스레드] 암묵적 스레딩 (스레드 풀, OpenMP, GCD)

등 긁는 봉황대 2022. 7. 14. 16:43

* 본 글은 '운영체제(Operating System: Concepts) 9th edition'의 내용과 2021학년도 1학기에 수강한 '운영체제' 과목 강의 내용을 함께 정리하여 작성하였습니다.

 

암묵적 스레딩 (Implicit Threading)


스레드의 생성과 관리에 대한 책임을 컴파일러와 실행시간 라이브러리에게 넘겨주는 것을 말한다.

( ↔︎ 명시적 스레딩 : 개발자가 API를 통해 직접 스레드를 관리 )

 

암묵적 스레딩은 개발자의 다중 스레드 응용 프로그램의 설계를 도와주는 한 가지 방법이며,

책에서는 이에 대한 3가지 접근법을 소개하고 있다.

 

스레드 풀(pool)

새로운 스레드를 매 요청마다 만들어주게 될 경우 아래와 같은 문제들이 발생한다.

1. 스레드를 생성하는 데에는 시간 소요가 발생

2. 무한정 새로운 스레드를 만들게 된다면 언젠가는 시스템 자원들이 고갈될 것

 

이에 대한 해결책으로 등장한 것이 스레드 풀이다.

즉, 프로세스를 시작할 때 일정한 수의 스레드들을 미리 풀(pool)로 만들어두는 것이다.

 

(1) 생성된 스레드들은 풀에서 일을 기다린다.

(2) 만약 한 개의 요청이 들어오면 이 풀에서 한 스레드에게 그것을 할당해주며,

(3) 해당 스레드가 요청을 다 서비스해주었다면 그 스레드는 다시 풀로 돌아가 다음 할당될 작업을 기다린다.

 

만약 풀에 남아 있는 스레드가 없다면 프로세스는 가용(free) 스레드가 하나 생길 때까지 기다려야 한다.

 

스레드 풀에 있는 스레드의 개수는 CPU의 수, 물리 메모리의 용량 등을 고려하여 정해질 수 있으며,

풀의 활용도를 보며 동적으로 풀의 크기를 바꾸어줄 수도 있다.

 

 

* 스레드 풀의 장점

 

1. 요청마다 새 스레드를 만들어 주는 것보다 기존 대기 중이었던 스레드로 서비스를 해주는 것이 더 빠르다.

 

2. 스레드 풀은 임의 시각에 존재할 스레드 개수에 제한을 두기 때문에

    많은 수의 스레드를 병렬 처리할 수 없는 시스템에 도움이 된다.

 

3. 태스크를 생성하는 방법을 태스크로부터 분리하면 태스크를 실행을 다르게 할 수 있다.

    ex. 태스크를 일정 시간 후에 실행되도록 스케줄 하거나 주기적으로 실행시킬 수 있음

 

* 3번은 도대체 무슨 의미인가.... 고민해보았는데, 스레드 풀을 통해서 해당 작업이 제때 진행되는 것을 보장시켜줄 수 있다는 뜻인 것 같다.

 

OpenMP

C, C++, 또는 FORTRAN으로 작성된 API & 컴파일러 디렉티브(Compiler Directive, 컴파일러 지시문)의 집합

개발자에게 공유 메모리 환경에서 병렬 프로그래밍을 할 수 있도록 도움을 준다.

 

병렬 영역이란, 병렬로 실행될 수 있는 블록(block, 독립적으로 실행될 수 있는 작업의 단위)을 말한다.

 

개발자가 코드에 병렬 영역에 컴파일러 디렉티브를 삽입하면

이 디렉티브는 OpenMP 실행시간 라이브러리에 해당 영역을 병렬로 실행하라고 지시하게 된다.

 

아래는 printf() 문을 포함하고 있는 병렬 영역 위에 컴파일러 디렉티브가 사용되고 있는 예시이다.

#include <omp.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
	/* sequential code */

	#pragma omp parallel
	{
		printf("I am a parallel region.");
	}

	/* sequential code */
        
	return 0;
}

 

OpenMP가 아래의  컴파일러 디렉티브를 만나게 되면,

#pragma omp parallel

시스템의 코어 개수만큼 스레드를 생성하며, 모든 스레드는 병렬 영역을 동시에 실행하게 된다.

 

필요한 스레드의 개수를 직접 설정하는 것도 가능하다.

 

Grand Central Dispatch (GCD)

Apple의 Mac OS X와 iOS 운영체제를 위한 기술이며,

이는 개발자가 병렬로 실행될 수 있는 영역을 식별할 수 있게 도와준다.

 

GCD는 블록을 식별하여 디스패치 큐에 넣는다. 아래는 블록의 예시이다. ({} 앞의 ^ 기호로 블록을 표시)

^{ printf("I am a block") }

 

디스패치 큐는 스레드 풀에서 가용 스레드를 선택, 이를 블록에게 할당하는 것으로 해당 블록이 실행될 수 있도록 스케줄링을 하는데,

GCD는 두가지 유형의 디스패치 큐를 갖는다.

 

1. 직렬(serial) 큐

블록은 FIFO 순서대로 제거된다.

블록은 큐에서 제거되면 다른 블록이 제거되기 전에 실행을 반드시 완료해야 한다.

 

2. 병렬(concurrent) 큐

직렬 큐와 동일하게 블록은 FIFO 순서대로 제거되나, 여러 블록이 동시에 제거될 수 있다.

따라서 블록들을 병렬로 실행하는 것이 가능하다.

 

 

반응형
Comments