Post

[OS] Operating System(4-1): Multicore Programming, Multithreading, Pthread

[OS] Operating System(4-1): Multicore Programming, Multithreading, Pthread

๐Ÿ€ ์šด์˜์ฒด์ œ ์ „๊ณต ์ˆ˜์—… ์ •๋ฆฌ

Single and Multithreaded Processes


alt text

  • single threaded process:
    • ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๋งŒ ์กด์žฌ
    • ๋ชจ๋“  ์ž์›์„ ๋‹จ์ผ ์Šค๋ ˆ๋“œ๊ฐ€ ์‚ฌ์šฉ
  • multithreaded process:
    • code, data, files๋ฅผ ๊ณต์œ 
    • registers, PC, stack: ์Šค๋ ˆ๋“œ๋ณ„ ๊ณต์œ  ์˜์—ญ

Multithreaded Server Architecture


alt text multithreaded Server์˜ ์ฒ˜๋ฆฌ๊ณผ์ •:

  1. client์˜ ์š”์ฒญ ์ ‘์ˆ˜
  2. ์š”์ฒญ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ ์ƒˆ ์Šค๋ ˆ๋“œ ์ƒ์„ฑ
  3. ๋‹ค๋ฅธ ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์„ ๋ฐ›๊ธฐ ์œ„ํ•ด ๋ฆฌ์Šค๋‹ ์ƒํƒœ๋กœ ๋ณต๊ท€

Benefit of Multithreading

  1. Responsiveness
    1. ํ”„๋กœ์„ธ์Šค ์ผ๋ถ€๊ฐ€ block ๋˜์–ด๋„ ๊ณ„์† ์‹คํ–‰ ๊ฐ€๋Šฅ
  2. Resource Sharing
    1. ์Šค๋ ˆ๋“œ๋Š” ํ”„๋กœ์„ธ์Šค์˜ ์ž์›์„ ๊ณต์œ 
    2. ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ๋‚˜ ๋ฉ”์‹œ์ง€ ์ „๋‹ฌ๋ณด๋‹ค ํšจ์œจ์ 
  3. Economy
    1. ํ”„๋กœ์„ธ์Šค ์ƒ์„ฑ๋ณด๋‹ค ์ €๋ ด
    2. ์Šค๋ ˆ๋“œ ์ „ํ™˜์ด context switching ๋ณด๋‹ค ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ๋‚ฎ์Œ
  4. Scalability
    1. Multicore architecture ํ™œ์šฉ ๊ฐ€๋Šฅ

Multicore Programming


Multicoreํ™˜๊ฒฝ์€ ๋ช‡๊ฐ€์ง€์˜ ๋„์ „๊ณผ์ œ๊ฐ€ ์žˆ์—ˆ๋‹ค.

  1. Dividing activities
  2. Balance
  3. Data splitting
  4. Data dependency
  5. Testing and debugging
  • Parallelism(๋ณ‘๋ ฌ): ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ฝ”์–ด/CPU๊ฐ€ โ€˜๋™์‹œ์—โ€™ ์—ฌ๋Ÿฌ๊ฐœ์˜ task๋ฅผ ์ง„ํ–‰ํ•จ, ์ง„์งœ๋กœ ๋™์‹œ์— ์—ฌ๋Ÿฌ ์ž‘์—…์ด ์‹คํ–‰(simultaneously) ๋˜๋Š” ๊ฒƒ
  • Concurrency(๋ณ‘ํ–‰): ํ•˜๋‚˜์˜ ์ฝ”์–ด/CPU๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ์˜ task๋ฅผ ์‹œ๊ฐ„์„ ๋ถ„ํ• ํ•ด์„œ ๋™์‹œ์— ์ง„ํ–‰ํ•จ(=scheduler)

alt text

single-core์˜ ๊ฒฝ์šฐ: ํ•˜๋‚˜์˜ ์ฝ”์–ด๊ฐ€ ์‹œ๊ฐ„์„ ์กฐ๊ฐ๋‚ด์–ด ์—ฌ๋Ÿฌ task๋ฅผ ๋ฒˆ๊ฐˆ์•„๊ฐ€๋ฉฐ ์‹คํ–‰. ์‹ค์ œ๋กœ๋Š” ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์ด์ง€๋งŒ, ๋น ๋ฅธ ์ „ํ™˜์œผ๋กœ ๋งˆ์น˜ โ€˜๋™์‹œ์—โ€™ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ž„
multi-core์˜ ๊ฒฝ์šฐ: ์—ฌ๋Ÿฌ ์ฝ”์–ด๊ฐ€ ๊ฐ๊ฐ ๋‹ค๋ฅธ task๋ฅผ ๋™์‹œ์— ์‹คํ–‰

Type of parallelism

  • Data parallelism: ๋™์ผํ•œ ๋ฐ์ดํ„ฐ์…‹์˜ ์—ฌ๋Ÿฌ ๋ถ€๋ถ„์„ ์—ฌ๋Ÿฌ ์ฝ”์–ด์— ๋ถ„๋ฐฐํ•˜์—ฌ ๋™์ผํ•œ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ์‹(์˜ˆ: ํฐ ์ด๋ฏธ์ง€๋ฅผ ์—ฌ๋Ÿฌ ๋ถ€๋ถ„์œผ๋กœ ๋‚˜๋ˆ„์–ด ๊ฐ ์ฝ”์–ด์—์„œ ๊ฐ™์€ ํ•„ํ„ฐ๋ฅผ ์ ์šฉํ•˜๋Š” ๊ฒฝ์šฐ)
  • Task parallelism: ์„œ๋กœ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๋ฅผ ์—ฌ๋Ÿฌ ์ฝ”์–ด์— ๋ถ„๋ฐฐํ•˜์—ฌ ๊ฐ ์Šค๋ ˆ๋“œ๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅธ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ์‹(์˜ˆ: ์›น ๋ธŒ๋ผ์šฐ์ €์—์„œ ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๋Š” UI๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ , ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๋Š” ๋„คํŠธ์›Œํฌ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒฝ์šฐ)

alt text

Amdahlโ€™s Law


๐Ÿ“š์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ฝ”์–ด๋ฅผ ์ถ”๊ฐ€ํ–ˆ์„ ๋•Œ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ์„ฑ๋Šฅ ํ–ฅ์ƒ์„ ์‹๋ณ„ํ•จ

  • ๊ฒฐ๋ก : ์ฝ”์–ด์˜ ์ˆ˜๊ฐ€ 2๋ฐฐ๊ฐ€ ๋œ๋‹ค๊ณ  ์„ฑ๋Šฅ์ด 2๋ฐฐ ์ข‹์•„์ง€์ง„ ์•Š๋Š”๋‹ค(1.6๋ฐฐ ํ–ฅ์ƒ)

alt text

S: ์ง๋ ฌ ๋ถ€๋ถ„ ๋น„์œจ(%), 1-S: ๋ณ‘๋ ฌ ๋น„์œจ, N: processing core ์ˆ˜
๋งŒ์•ฝ ์–ด๋–ค task์˜ 75%๊ฐ€ ๋ณ‘๋ ฌ์ด ๊ฐ€๋Šฅํ•˜๊ณ  ๋‚˜๋จธ์ง€๋Š” ์ง๋ ฌ๋งŒ(25%) ๊ฐ€๋Šฅํ•  ๋•Œ, ์ฝ”์–ด๊ฐ€ 2๋ฐฐ๊ฐ€ ๋˜๋ฉด ์ตœ๋Œ€ ํšจ์œจ์€ 1.6๋ฐฐ์ด๋‹ค.
์ฆ‰, ์ตœ๋Œ€์˜ speedup์„ ์œ„ํ•ด์„  ์ง๋ ฌ๋งŒ ๊ฐ€๋Šฅํ•œ ํ”„๋กœ๊ทธ๋žจ์ด ์ ์–ด์•ผํ•œ๋‹ค

alt text

S๊ฐ€ 50%์ธ ๊ฒฝ์šฐ ์•„๋ฌด๋ฆฌ core๋ฅผ ๋Š˜๋ ค๋„ speed๊ฐ€ 2๋ฐฐ๊ฐ€ ๋˜์ง€ ์•Š๋Š”๋‹ค.

User Threads and Kernel Threads


โœ… process์™€ thead๋ฅผ ํ˜ผ๋™ํ•  ์ˆ˜ ์žˆ๋‹ค โ†’ ํ˜„์žฌ๋Š” ๊ฑฐ์˜ ๋ชจ๋‘ thread๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
์˜›๋‚ ์—๋Š” process๋‹จ์œ„๋กœ scheduler๋ฅผ ํ–ˆ์ง€๋งŒ ํ˜„์žฌ๋Š” thread ๋‹จ์œ„๋กœ ํ•จ

  • User threads: management done by user-level threads library
  • Three primary thread libraries:
    • POSIX Ptheads: thread์˜ ์‹œ๋ฐœ์  / ํ˜„์žฌ๋Š” kernel level
    • Windows threads
    • Java threads
  • Kernel threads: Supported by the Kernel
  • ๋Œ€๋ถ€๋ถ„์˜ ํ˜„๋Œ€ ๋ฒ”์šฉ ์šด์˜์ฒด์ œ์—์„œ ์ง€์›:
    • Windows
    • Linux
    • Mac OS X
    • iOS
    • Andriod

alt text

๊ฐœ๋…์ ์œผ๋กœ๋Š” user์™€ kernel์ด ๋ถ„๋ฆฌ๋จ

๊ทธ ๋ถ„๋ฆฌ๋ฅผ ํ•ฉ์น˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

1. Many-to-One


๐Ÿ“šMany-to-One: ์—ฌ๋Ÿฌ User Thread๊ฐ€ ํ•˜๋‚˜์˜ Kernel Thread์— Mapping๋˜๋Š” ๋ฐฉ์‹

alt text

โœ…์žฅ์ :

  • ์›ํ•˜๋Š” ๋งŒํผ ๋งŽ์€ ์‚ฌ์šฉ์ž ์Šค๋ ˆ๋“œ ์ƒ์„ฑ ๊ฐ€๋Šฅ

โŒ๋‹จ์ :

  • ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ๋ถˆ๊ฐ€๋Šฅ โ†’ ๋ฉ€ํ‹ฐ์ฝ”์–ด์˜ ์žฅ์  ๋ชป ์‚ด๋ฆผ
  • ํ•˜๋‚˜๋ผ๋„ ๋ธ”๋กœํ‚น๋˜๋ฉด ์ „๋ถ€ ๋ฉˆ์ถค โ†’ ํšจ์œจ์„ฑ ์ €ํ•˜ ํ˜„์žฌ๋Š” ๊ฑฐ์˜ ์‚ฌ์šฉ X

2. One-to-One


๊ฐ ํ•˜๋‚˜์˜ ์œ ์ € ์Šค๋ ˆ๋“œ์— ์ปค๋„ ์Šค๋ ˆ๋“œ๊ฐ€ ๋งคํ•‘๋จ โ†’ user thread๋ฅผ ์ƒ์„ฑํ•˜๋ฉด kernel thread๋„ ํ•จ๊ป˜ ์ƒ์„ฑ๋จ

โœ…์žฅ์ :

  • ์Šค๋ ˆ๋“œ๊ฐ€ ๋ธ”๋กœํ‚น๋˜์–ด๋„ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ ์‹คํ–‰ ๊ฐ€๋Šฅ
  • ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๋ฅผ ๋‹ค์ค‘์ฝ”์–ด์— ๋งคํ•‘ ๊ฐ€๋Šฅ

โŒ๋‹จ์ :

  • ์Šค๋ ˆ๋“œ ์ƒ์„ฑ ์‹œ ์˜ค๋ฒ„ํ—ค๋“œ ๋•Œ๋ฌธ์— ํ”„๋กœ์„ธ์Šค๋‹น ์Šค๋ ˆ๋“œ ์ˆ˜๊ฐ€ ์ œํ•œ๋  ์ˆ˜ ์žˆ์Œ

3. Many-to-Many Model


์—ฌ๋Ÿฌ๊ฐœ์˜ ์œ ์ € ์Šค๋ ˆ๋“œ๋ฅผ ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ปค๋„ ์Šค๋ ˆ๋“œ์— ๋งคํ•‘๋˜๋Š” ๋ฐฉ์‹

โœ…์žฅ์ :

  • ์‚ฌ์šฉ์ž ์Šค๋ ˆ๋“œ๋ฅผ ๋งˆ์Œ๋Œ€๋กœ ์ƒ์„ฑ ๊ฐ€๋Šฅ + ๋ฉ€ํ‹ฐ์ฝ”์–ด์—์„œ ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰๊ฐ€๋Šฅ

โŒ๋‹จ์ :

  • ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ž…๋ ฅ๊ณผ ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ถœ๋ ฅ์„ ์Šค์œ„์นญํ•ด์ค˜์•ผํ•˜๋Š”๋ฐ ๊ทธ ๋น„์šฉ์ด ์ƒ๋‹นํ•จ โ†’ ๊ตฌํ˜„์ด ์–ด๋ ค์›€

Thread Library


๐Ÿ“šThread Library: ํ”„๋กœ๊ทธ๋ž˜๋จธ์—๊ฒŒ ์Šค๋ ˆ๋“œ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” API(Application Programming Interface)๋ฅผ ์ œ๊ณต

์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ๋‘ ๊ฐ€์ง€ ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„:

  1. user space์—๋งŒ ์žˆ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ:
    • ๋ชจ๋“  ์Šค๋ ˆ๋“œ ์ฝ”๋“œ๊ฐ€ ์‚ฌ์šฉ์ž ๊ณต๊ฐ„์—์„œ ์‹คํ–‰๋จ
    • ์ปค๋„์€ ์Šค๋ ˆ๋“œ์˜ ์กด์žฌ๋ฅผ ์ธ์‹ํ•˜์ง€ ๋ชปํ•จ
  2. kernel-level์—์„œ ์ง€์›ํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ:
    • ์Šค๋ ˆ๋“œ ์ƒ์„ฑ ๋ฐ ๊ด€๋ฆฌ๊ฐ€ ์ปค๋„์— ์˜ํ•ด ์ˆ˜ํ–‰๋จ
    • ์‹œ์Šคํ…œ ์ฝœ์„ ํ†ตํ•ด ์ปค๋„๊ณผ ํ†ต์‹ 
  • Asynchronous Threading: ๋ถ€๋ชจ์™€ ์ž์‹ ์Šค๋ ˆ๋“œ๊ฐ€ ๋…๋ฆฝ์ ์œผ๋กœ ๋ณ‘ํ–‰ ์‹คํ–‰
  • Synchronous Threading: ๋ถ€๋ชจ ์Šค๋ ˆ๋“œ๋Š” ๋ชจ๋“  ์ž์‹ ์Šค๋ ˆ๋“œ๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆผ

    ๋ถ€๋ชจ ์Šค๋ ˆ๋“œ๋Š” ๋ฉ”์ธ ์Šค๋ ˆ๋“œ, ์ž์‹ ์Šค๋ ˆ๋“œ๋Š” ์„œ๋ธŒ ์Šค๋ ˆ๋“œ๋ผ๊ณ ๋„ ํ•œ๋‹ค.
    POSIX Pthreads: user or kernel level
    Windows threads: kernel level
    javathreads: depending on OS

Pthreads


์‚ฌ์šฉ์ž ์ˆ˜์ค€์ด๋‚˜ ์ปค๋„ ์ˆ˜์ค€์œผ๋กœ ์ œ๊ณต๋  ์ˆ˜ ์žˆ์Œ

  • ์Šค๋ ˆ๋“œ ์ƒ์„ฑ ๋ฐ ๋™๊ธฐํ™”๋ฅผ ์œ„ํ•œ API
  • ํ‘œ์ค€๋งŒ ์ •์˜: ์‹ค์ œ ๊ตฌํ˜„์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ฐœ๋ฐœ์ž์—๊ฒŒ ๋งก๊น€

์Šค๋ ˆ๋“œ ์ƒ์„ฑ

1
2
3
4
#include <pthread.h>

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                  void *(*start_routine)(void *), void *arg);
  • thread: ์ƒ์„ฑ๋œ ์Šค๋ ˆ๋“œ์˜ ID๋ฅผ ์ €์žฅํ•  ํฌ์ธํ„ฐ
  • attr: ์Šค๋ ˆ๋“œ์˜ ์†์„ฑ(NULL์ด๋ฉด ๊ธฐ๋ณธ๊ฐ’)
  • start_routine: ์Šค๋ ˆ๋“œ๊ฐ€ ์‹คํ–‰ํ•  ํ•จ์ˆ˜ ์ฃผ์†Œ
  • arg: ์‹œ์ž‘ ํ•จ์ˆ˜์— ์ „๋‹ฌํ•  ์ธ์ž
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/* Example pthread */

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

int sum; /* this data is **shared** by the thread(s) */
void *runner(void *param); /* threads call this function */

int main(int argc, char *argv[])
{
  pthread_t tid; /* ์Šค๋ ˆ๋“œ ์‹๋ณ„์ž */
  pthread_attr_t attr; /* ์Šค๋ ˆ๋“œ ์†์„ฑ ์ง‘ํ•ฉ */

  /* set the default attributes of the thread */
  pthread_attr_init(&attr);
  /* create the thread */
  pthread_create(&tid, &attr, runner, argv[1]);
  /* wait for the thread to exit */
  pthread_join(tid, NULL);

  printf("sum= %d\n", sum);
}

void *runner(void *param)
{
  int i, upper=atoi(param);
  sum =0;
  for(i=1; i<=upper; i++)
    sum += i;

  pthread_exit(0);
}

// 10๊ฐœ์˜ ์Šค๋ ˆ๋“œ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์™„์ „ํžˆ ์ข…๋ฃŒ๋  ๋•Œ๊นŒ์ง€ main thread๊ฐ€ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ฝ”๋“œ
#define NUM_THREADS 10

/* an array of threads to be joined upon */
pthread_t workers[NUM_THREADS];

for(int i = 0; i<NUM_THREADS; i++)
  pthread_join(workers[i], NULL); // ์Šค๋ ˆ๋“œ ์ข…๋ฃŒ ๋Œ€๊ธฐ
This post is licensed under CC BY 4.0 by the author.