2. Thread

EEEFFEE·2023년 7월 7일
0

운영체제

목록 보기
3/8

23.07.07 최초 작성

1. Thread

프로그램에서 하나의 실행 상태를 나타내는 단위. 하나의 프로세스에 여러 스레드가 존재 가능하며 이 스레드들은 코드, 전역변수, 힙 영역, 열려있는 파일 등 프로세스의 메모리 영역을 공유한다. 하지만 레지스터, PC, SP를 공유하지 않는다.
cpu에 실행시킬 프로그램을 결정하는 스케줄링의 단위이다.

  1. Single-threaded process
    하나의 프로그램에 쓰레드가 1개 존재하는 형태 (context가 1개)

  2. Multi-threaded process
    하나의 프로그램에 쓰레드가 2개 이상 존재하는 형태(context가 여러개)

장점

  • 멀티코어 구조를 온전히 활용 가능하다.
  • 프로그램간의 자원의 공유가 명확해진다.
  • 프로그램 구조를 향상시킬 수 있다.
  • 스루풋과 반응성이 좋다.
  • Concurrency
    여러개의 작업이 조금씩 동시에 진행할 수 있는 시스템의 성질

  • Parallelism
    기계적(하드웨어적)으로 동시에 여러 작업을 동시에 실행할 수 있는 시스템의 성질

  • Data Parallelism
    다른 코어에 각 데이터를 나눠 같은 작업을 진행하는 형태

  • Task Parallelism
    각 다른 작업을 다른 코어에 나눠 작업하는 형태

1.1 Amdahl's Law


추가적인 자원을 할당했을 때 처리속도의 향상되는 정도를 수식으로 나타낸 것

SPN
단일 처리 하는 부분병렬 처리 하는 부분코어 갯수

2. Multithreading Model

2.1 스레드의 종류

2.1.1 Kernel Threads

  • 운영체제가 직접 지원하고 관리하는 스레드
  • 스케줄링의 단위

2.1.2 User Threads

  • 유저 레벨 스레드 라이브러리를 통해 생성되고 관리되는 스레드(virtual thread)
  • 커널 스레드에 매핑되어 스케줄링 됨

2.2 Kernel Threads와 User Threads의 관계

2.2.1 One-to-One

  • 각 유저 레벨 스레드가 커널 스레드에 1대 1 대응 되는 형태
  • 유저 레벨 스레드가 커널 스레드 하나를 생성
  • 프로세스가 담을 수 있는 스레드 갯수가 제한되어 있음
  • Concurrency가 Many-to-One보다 뛰어남

2.2.2 Many-to-One

  • 각저 레벨 스레드가 커널 스레드에 다대 1 대응 되는 형태
  • 유저 스레드간에 컨텍스트 스위칭이 적게 일어남
  • 하나의 커널스레드가 하나의 cpu에 매핑되기 때문에 코어를 여러개 사용할 수 없음
  • 하나의 유저 스레드가 멈출 시 모든 유저 스레드가 멈추게 됨

2.2.3 Many-to-Many

  • 각저 레벨 스레드가 커널 스레드에 다대 다 대응 되는 형태
  • 프로세스가 담을 수 있는 스레드 갯수가 여러개가 될 수 있음

3. Thread Libraries

사용자가 API로 스레드를 생성하고 관리할 수 있도록 하는 라이브러리

3.1 pthread

#include<stdio.h>
#include<pthread.h>

int values[4] = {0,1,2,3};
void *hello(void * arg)
{
	printf("hello, world\n");
}

int main()
{
	pthread_t tid;
    pthread_create(&tid, NULL, hello, NULL);
    printf("hello from main thread\n");
}
int pthread_create (pthread_t *tid, pthread_attr_t *attr,
					void*(start_routine)(void*), void *arg);
                    
void pthread_exit (void *retval);
int pthread_join (pthread_t tid, void **thread_return);

라이브러리로 제공되기 때문에 컴파일 시 링크 해줘야 함

4. Implicit Threading

스레드의 생성과 관리 책임을 개발자가 하는것이 아닌 컴파일러와 런타임 라이브러리에게 넘겨주는 것

4.1 Thread Pool

스레드를 일정 수 대기상태로 두고 스레드 생성 요청을 받으면 이 스레드 중 하나에게 작업을 할당한다. 작업이 종료되면 다시 스레드를 대기상태로 되돌린다.
스레드의 최대 갯수는 풀의 크기에 의해 제한되며 스레드를 생성할 필요가 없기 때문에 실행속도가 약간 더 빠르다.

4.2 Fork Join

메인 부모 스레드가 하나 이상의 자식 스레드를 fork한 다음 자식의 종료를 기다린 후 join하고 그 시점 부터 자식의 결과를 확인하고 결합하는 방법. Divede & Conquer 기법을 이용할 때 유용함.

4.3 OpenMP

컴파일 과정에서 컴파일러가 멀티스레딩을 공유할 수 있도록 하는 방법. 공유 메모리 환경에서 병렬 실행을 가능하게 한다.

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

int a[4] = {0,1,2,3};
int b[4] = {0,1,2,3};
int c[4] ;

int main(){
 
 	// 병렬 영역 선언
   #pragma omp parallel for
   for (int i = 0; i < 4; i ++){
    	c[i] = a[i] + b[i];
   }
    
   #pragma omp parallel
   {
   	printf("I am a parallel region");
   }
   
   return 0;
}

5. Threading Issue

5.1 fork() & exec()

fork() 호출 시 새로운 프로세스는 특정 스레드만 복제하는 방법과 모든 스레드를 복제하는 방법을 모두 제공한다.
pthread 환경에서는 특정 스레드만을 복제하지만 UNIX 환경에서는 모든 스레드를 복제하는 fork(), 특정 스레드만을 복제하는 fork1()을 지원한다.
exec()의 경우 호출 시 프로세스와 프로세스의 모든 스레드를 초기화한다.

5.2 Signal Handling

받은(인바운드) 시그널에 대해 어떤 스레드가 신호를 처리할 지 정해야 한다.

5.3 Thread Cancellation

스레드가 작업을 완료하기 전 스레드를 종료시키는 작업

  1. Asynchronous cancellation
    어떤 스레드가 타겟 스레드를 바로 강제 종료한다.
  2. Deferred cancellation
    타겟 스레드가 주기적으로 종료 확인 지점(cancellation point)에서 강제 종료 신호를 확인한다. 타겟 스레드가 순서에 맞게 종료될 수 있도록 할 수 있다.
ptherad_cancel

5.4 Thread-Local Storage(TLS)

스레드가 다른 스레드와 공유하지 않고 자신만 접근할 수 있는 데이터. 함수가 호출되는 동안 존재하는 지역변수와 다르게 스레드 전체에 걸쳐 존재한다.

__thread int TLS_var=0;		//TLS 선언

사용 예

  1. TLS를 사용하면 글로벌 변수의 동기화를 고려하지 않아도 된다.
  2. errno 값을 다룰 때 사용되며 스레드마다 errno를 다르게 할 수 있다.

6. Thread in Linux

리눅스에서 스레드는 'task'라고 하며 task_struct를 통해 스레드처럼 가상화된다. clone()이란 시스템 콜로 생성된다.

0개의 댓글