Chapter4. Multithreaded Programming

4.1 Overview

Thread란?

  • basic unit of CPU utilization이다.
  • Process의 control flow이기도 하다.

Thread의 장점

  • Resposiveness : 어떤 코드 일부가 막혀있거나 다른 일을 하고 있더라도 유저의 요청에 즉각 대응할 수 있다.
  • Resource Sharing : 프로세스는 shared memory나 message passing을 이용해서 리소스를 공유하지만 thread는 그냥 데이터를 공유한다. 기술이 필요하지 않다. (Global Variables)
  • Economy : 생성 비용이 작다(리소스 카피를 안해서 그렇단다.)
  • Scalability : 멀티 코어 일 때 계속해서 성능이 더 좋아진다.

Process와 차이점

  • 프로세스는 생성하는데 비용과 시간이 큼, 리소스를 카피 해야하기 때문에
  • 만일 같은 일을 할거라면 리소스 카피는 무의미하다.
  • 쓰레드는 리소스 카피 안해서 시간이 훨 짧게 듬. 뿐만 아니라 데이터 공유가 쉬움

4.2 Multicore Programming

CPU 안에 코어가 여러개 있다면 multi core라고 한다. 각 코어가 control을 잡고 Multithreaded Programming을 할 수 있다.

Parallelism vs. concurrency

parallel하다 : 하나 이상의 태스크를 동시에 작업한다.(doing) concurrent하다 : 동시에 하나 이상의 태스크를 다룬다.(dealing)

찾다보니 이게 제일 정확한거 같다.

사진

위의 그래프를 보듯이 parallelism은 말그대로 하나 이상의 일이 동시에 진행되는 거고 concurrency는 여러개의 일을 진행하되 context switch 등을 이용해서 더 효율적으로 여러가지 일을 진행하는 것을 의미한다.

programming challenges

  1. identify tasks : task 쪼개기 어려워
  2. balance : 이전 만큼의 퍼포먼스가 나와야 함
  3. data splitting : 데이터를 각각에게 맞게 줘야할 텐데
  4. data dependency : 데이터 sync 잘못 맞추면 큰일나
  5. test & debugging : 일이 동시에 여러개 진행되니까 디버깅 쉽지않아.

Type of Parallelism

  • Data Parallelism : 데이터의 subset을 분배하는데 초점
  • Task Parallelism : task를 각 코어에 분배하는데 초점

Multithreading Models

첫번째. Many-to-One

사진

  • Many Users to One Kernel
  • system call이 막히면 다 막힘
  • kernel이 하나 이기 때문에 multi-core 효과 없음.

두번째. One-to-One

사진

  • 하나의 유저당 하나의 kernel 쓰레드
  • Syscall 다 괜춘 Multi도 잘됨
  • 근데 문제는 kernel을 너무 많이 만들어야 되서 Application한테 너무 무거운 짐을 주는 걸 수도…

세번째. Many-to-Many

사진

  • 여러 유저가 적당량의 커넬을 돌려 쓸 수 있다. 아주 좋아.
  • Application에게 지우는 짐이 무겁지 않다.

사진

  • 이런식으로 one to one 과 many to many를 동시에 쓰는 two-level model도 있다.

4.4 Thread Libraries

Thread를 위한 API같은 친구들이다.

방법은 두가지이다.

  1. 유저단에서 library를 import해서 쓰는 방법
  2. kernel level에서 os가 제공하는 thread library를 쓰는 방법

Thread Library 3개

  • pthread : Posix Standard extension
  • windows - kernel window
  • java - Java programming 에서 JVM은 host OS의 Library를 사용

async & sync thread 방법

async - child와 parent thread가 동시에 일해 concurrently sync - wait for children to terminate => fork-join, 데이터 쉐어링에 용이

pthread implementation

쓰레드 생성(create)

pthread_t tid; /* the thread identifier */
/* create the thread */
pthread_create(&tid,&attr,runner,argv[1]);

쓰레드 끝날 때까지 기다림(join)

pthread join(tid,NULL);

이 두과정을 통해서 thread 순서를 정할 수도 있다.

4.5 Implicit Threading

  • Thread는 Correctness를 확인하기가 어렵다.
  • 그 밖에 앞에서 명시한 challenge 들을 보완해야 한다.

=> 이를 위해 implicit threading을 한다.

Thread Pool

  • 매번 쓰레드가 생성되는 낭비를 방지하기 위해서 사용
  • thread를 미리 준비해놓고 작업을 할 때 쉬고 있는 thread를 사용
  • 이 경우 생성시간을 줄일 수 있다. concurrent threading 가능

Open MP

parallel할 구간을 미리 명시

#pragma omp parallel

4.6 Threading Issues

Fork랑 Exec 문제

  • fork하면 process의 모든 thread를 복사할건가? 아님 지금 fork를 호출한 Thread만?
  • 둘다 지원하니 잘 선택하시게
  • exec은 process를 replace한다 즉 지금 호출한 thread말고 다 죽여버리니까 조심해서 써

Signal Handling 문제

  • Signal은 event 발생으로 생겨나서 프로세스에 전달되는데
  • 프로세스에 전달되서 시그널을 핸들하게 된다.
  • Sync - illegal use of memory
  • Async - 외부 event에 의해 보내짐
  • multithread는 쓰레드가 뭐를 받을 지 명시할 수 있게 되있다.

Thread Cancellation 문제

쓰레드를 종료하는 두가지 방법

  1. Async cancellation : thread가 다른 하나의 thread를 선택해서 사살
  2. Deferred cancellation : 내가 죽어야 하나 계속 확인(periodically)

async가 문제야 왜냐면 다른 애를 선택해서 죽이는 중에 resource가 할당 되거나 죽은지 모르고 resource를 할당하게 될 수도 있다.

그래서 deferred cancellation을 보통 default로 사용합니다.

그 밖에 thread-local storage 문제와 scheduler activations 문제가 있다.

Summary

A thread is a flow of control within a process. A multithreaded process contains several different flows of control within the same address space. The benefits of multithreading include increased responsiveness to the user, resource sharing within the process, economy, and scalability factors, such as more efficient use of multiple processing cores. User-level threads are threads that are visible to the programmer and are unknown to the kernel. The operating-system kernel supports and manages kernel-level threads. In general, user-level threads are faster to create and manage than are kernel threads, because no intervention from the kernel is required. Three different types of models relate user and kernel threads. The many- to-one model maps many user threads to a single kernel thread. The one-to-one model maps each user thread to a corresponding kernel thread. The many-to- many model multiplexes many user threads to a smaller or equal number of kernel threads. Most modern operating systems provide kernel support for threads. These include Windows, Mac OS X, Linux, and Solaris. Thread libraries provide the application programmer with an API for creating and managing threads. Three primary thread libraries are in common use: POSIX Pthreads, Windows threads, and Java threads. In addition to explicitly creating threads using the API provided by a library, we can use implicit threading, in which the creation and management of threading is transferred to compilers and run-time libraries. Strategies for implicit threading include thread pools, OpenMP, and Grand Central Dispatch. Multithreaded programs introduce many challenges for programmers, including the semantics of the fork() and exec() system calls. Other issues include signal handling, thread cancellation, thread-local storage, and scheduler activations.

  • Opearting System Concepts Ninth Edition by Abraham Silberschatz 참조