본문 바로가기
CS/Operating System

[Operating System Concepts] Chapter4 Thread & Concurrency

by 개복취 2023. 10. 31.

짱룡

  1. Overview
  2. Multicore Programming
  3. Multithreading Model
  4. POSIX thread(pthread)
  5. Implicit Threading

Overview

  • 지금까지 하나의 프로세스의 single thread control에 다루었다.
  • 복제할 필요없이 하나의 프로세스에서 다른 스레드를 생성하는 방식으로 만들었다.

Thread (=LWP : Light weight process)

  • cpu 를 점유하는 가장 작은 단위가 스레드가 된다.
  • process id(pid) 가 cpu를 점유하는게 아니라 thread id(tid)가 cpu를 점유한다.
  • program counter, register set, stack또한 스레드 단위로 달라진다.

  • 한 프로세스 내부에서 생긴 스레드들은 code / data / files 영역의 정보에 대해서는 공통으로 들고 있다.
  • register / stack / pc 같은 경우에는 단독으로 들고있는 상태가 된다면 멀티 스레딩의 필요조건을 만족시킨다.

  • 소켓에서 리스닝하고 있을 때 데이터를 주고 받는 과정에서 많은 데이터를 받아올 때, 스레드에게 처리를 부탁하면 서버는 자기일만 할 수 있기 때문에 효율성이 극대화된다.

 

멀티스레딩을 사용하여 얻게되는 장점은 4가지가 있다.

  1. 응답성(Responsiveness) : user interface등을 처리할 때 non-blocked로 execution 실행 가능하다.
  2. 자원공유(Resource Sharing) : 스레드는 코드와 데이터 영역을 공유한다. 굳이 shared memory를 만들지 않아도
    shared memory처럼 사용가능하다. → 자원공유가 용이하다.
  3. 경제성(Economy) : 프로세스를 복사해서 사용하는것과 스레딩하는 경우를 비교했을 때 스레딩하는게 값이 싸고, 컨텍스트 스위칭에도 용이하다.
  4. 확장성(Scalability) : 프로세스는 멀티프로세스 단위일 때 병렬처리까지 가능하게 된다.

(사실상 스레드를 배우기위해 프로세스를 공부하는것이라고 볼 수 있다...)

 

 

Multicore Programming

single-core / concurrency

  • 싱글코어 : 스레드는 시간지남에 따라 사이에 끼워넣기(interleaved) 된다. 병행성(concurrency)의 정수이기도 하다.

multi-core / parallel

  • 멀티코어 : 시분할(time-sharing)을 하면서 코어를 나눠가면서 병렬적(parallel)으로 처리할 수 있다.

병행성(concurrency) vs. 병렬성(parallel)

  • 병행 시스템은 모든 작업이 진행되게 하여 둘 이상의 작업을 지원한다. (싱글코어)
  • 병렬성은 둘 이상의 작업을 동시에 수행할 수 있다. (멀티코어)
  • 따라서, 병렬성 없이 병행성을 가질 수 있다.

Challenge of Programming

  1. Identifying tasks: 쪼개는 단위나, 의존성(dependency) 등을 어떻게 쪼개야 하는 방법들의 작업
  2. Balancing: 스레드가 일찍끝나거나, 늦게 끝나는 경우들에 케어를 해야하기 때문에 밸런싱해주어야한다.
  3. Data splitting: 각 코어에 들어가는 데이터들에 대해 나눠주기
  4. Dependency : 동기화가 잘 이뤄져야지 mergesort 같은 작업이 일어날 수 있다.
  5. Test & Debugging : 멀티스레딩을 하게된다면 디버깅과 테스팅이 매우 어려워진다.

 

data, task parallelism / Amdhal's Law

왼: 병렬성의 종류로 데이터 병렬성, 작업 병렬성이 존재한다. 요즘은 분산처리하는 단계로 넘어가서 구분을 따로 두지 않는다.

오: 암달의 법칙 : 코어는 많을수록 좋은가? (결론: 일정수준 넘어가면 그닥 좋은 성능 보여주지 못한다.)

Multithreading Model

  • 두가지 종류의 스레드가 있음 user thread, kernel thread
  • JVM은 컨트롤을 동시성(concurrent) 있게 실행할 수 있을 뿐이지, cpu내부의 코어를 끌어다가 쓸 수 없다는 이슈가 있다.
     user thread 로 한정됨
  • 코어에서 스레딩할 수 있는 스레드를 운영체제에서 생성한다.
     native thread(kernel thread)
  • user thread는 커널 위의 user mode에서 스레딩 되는것을 이야기하고 kernel thread는 OS 위에서 컨트롤 하는 것을 의미한다.

 

3가지 종류의 multithreading model(N:1, 1:1, N:N)

 

Many to One model

많은 사용자 수준 스레드가 하나의 커널 스레드에 연관됨

 

[장점]

  • 스레드 라이브러리에 의해 스레드가 관리되므로 효율적이다.

[단점]

  • 한번에 하나의 스레드에만 커널에 접근이 가능하다.
  • 다중 스레드가 다중 코어 시스템에서 병렬 실행 불가능
  • 다중 처리 코어의 이점을 살릴 수 없다.
  • 동시성은 있지만 병렬성은 없다.

 

 

 

 

One to One model

사용자 스레드가 각각 하나의 커널 스레드와 연관됨

 

 

[장점]

  • 다대일 모델보다 더 많은 병렬성을 제공해준다.
  • 다중 스레드가 병렬로 수행하는것을 허용한다.

[단점]

  • 유저스레드 하나를 만들려면 커널 스레드를 하나 더 만들어야 해서 성능에 부담이 될 수 있다.

Linux, Windows OS에서는 대부분 이러한 모델로 구현되어 있다.

 

 Many to Many model

여러 개의 사용자 수준 스레드를 그보다 작은 수, 혹은 같은 수의 커널 스레드로 멀티플렉스 한다. 커널 스레드의 할당은 응용 프로그램 또는 기계에 따라 달라진다.

[장점]

  • 개발자는 필요한 만큼 사용자 수준 스레드를 생성할 수 있고, 상응하는 커널 스레드가 병렬 수행될 수 있다.
  • 스레드가 blocking 처리할 때 커널이 다른 스레드의 수행을 스케쥴링 할 수 있다.

[단점]

  • 구현하기 어렵다. 그리고 굳이 구현할 필요가 없다. 

 

POSIX thread(pthread)

  • posix thread library (pthread)는 사용자 또는 커널 수준 라이브러리로 제공된다.
#include <pthread.h>

pthread_t tid; // thread identifier
pthread_attr_t attr; // thread attributes

pthread_attr_init(&attr);
pthread_create(&tid, &attr, runner, argv[1]);
pthread_join(&tid, NULL);

위의 내용을 컴파일 할 때 gcc '-pthread' 옵션을 줘야지 스레드가 실행 가능하다.

 

Implicit Threading

컴파일러와 실행시 라이브러리에 일을 위임하는 방식

  • 골치아픈 스레딩 작업을 알아서 해주는 방법(java : executor framework)
  • java.concurrent 의 패키지에 해당 라이브러리를 제공한다.
  • 컴파일러는 OpenMP를 사용한다.

스레딩 풀을 사용하는 대표적인 WAS 톰캣 vs. 단일스레드 비동기처리 최강자 Nginx

  • 4가지 종류의 Implicit Threading 이 존재한다. 
    1. Thread Pools : 스레드 풀을 만들어서 getter으로 스레드를 가져온다.
      → 평소에는 일 없이 기다리고 있다가 요청을 받으면 서비스 한다.
      • 기존 스레드로 서비스 하는것이 새 스레드를 만드는 것보다 더 빠를 수 있다.
      • 스레드 풀은 존재할 스레드 개수에 제한을 둔다. 이는 병렬 처리 불가한 시스템에 도움을 준다.
      • 태스크 생성하는 방법을 기존의 태스크로부터 분리해서 실행시킬 수 있다.
    2. Fork & Join : 포크하고 조인하는 과정을 통해 explicit하게 했지만 생성과 관리를 라이브러리에게 떠맡긴다면, implicit하게 스레딩을 할 수 있다고 볼 수 있다.
    3. Open MP : 컴파일러 지시어를 줘서 C/C++에서 병렬처리가 가능하도록 한다. (#pragma omp parallel 아래 예시코드)
    4. GCD (iOS)

fork & join 책임을 사용자가아닌 라이브러리에게 위임

omp set num_threads(4)

#pragma omp parallel for // 병렬영역 선언, 출력의 순서는 보장되지 않는다.
for(i = 0; i < SIZE; i++) {
	c[i] = a[i] + b[i];
}

More about Thread pool: https://www.youtube.com/watch?v=B4Of4UgLfWc

multithreading model: https://howudong.tistory.com/268

 

[OS] 다중 쓰레드 모델(Multi-Thread Model) 종류

다중 스레드 모델(MultiThreading Model) 수준 차이에 따른 스레드 지원 사용자 스레드(user threads) : 사용자 수준에서 지원하는 스레드 커널 위에서 지원되고 커널의 지원 없이 관리 커널 스레드(ker-nel t

howudong.tistory.com