[Kotlin] 동시성, 병렬성, 스레드, 코루틴

틀린 내용이 있다면 댓글로 알려주세요!

스레드

스레드란?

프로세스 내의 작업 단위

하드웨어적으로 구현된 스레드와 소프트웨어적으로 구현된 스레드

하드웨어적으로 구현된 스레드

하드웨어적으로 구현된 스레드를 쉽게 물리적 스레드라고 하겠습니다.
물리적 스레드를 알기 전에 먼저 코어가 무엇인지 알아봅시다.

  • 코어 : CPU에 내장된 처리회로. 명령어를 메모리에서 뽑아 해석하고 실행하는 반도체 유닛.

CPU는 다수의 코어를 장착할 수 있습니다. 최근에 나오는 듀얼 코어(2코어), 쿼드 코어(4코어), 옥타 코어(8코어) 등이 그 개념입니다. 코어의 수가 증가할수록 CPU의 처리 속도는 빨라집니다. 싱글 코어에서 2번 해야될 연산을 듀얼 코어에서는 한번에 수행하여 완료할 수 있습니다. 다만, 코어가 증가할 수록 클럭(코어당 연산의 속도)가 낮아진다는 단점이 있습니다. 하지만 코어의 갯수가 많다 하더라도 실행하는 소프트웨어가 다중 코어 연산을 지원해야 합니다. 그렇지 않다면 쿼드 코어에서 실행하나 싱글 코어에서 실행하나 차이가 없을 것입니다.

  • 물리적 스레드 : 하나의 코어가 허용할 수 있는 스레드

과거에는 하나의 코어에 하나의 스레드로 데이터를 처리했습니다. 다시말해, 코어에서 동시에 실행 가능한(할당 가능한) 스레드 수가 1개였다는 의미입니다. 마치 1차선 도로와 같습니다. 인텔사에서는 스레드 하나로는 코어의 성능을 100%발휘할 수 없으니 여러 스레드를 동시에 적용시키자는 생각을 합니다. 그 결과 코어에서 2개 이상의 스레드를 적용하여 프로그램을 실행할 수 있는 하이퍼 스레딩 개념이 발생합니다. 컴퓨터 성능을 따질때 얘기하는 스레드가 바로 이것입니다. 1개의 코어의 2개의 스레드가 들어있다면 보통 2코어 4스레드, 4코어 8스레드 등으로 불립니다. 1개의 코어에서 2개의 스레드를 실행 가능하게 되는 것입니다.

소프트웨어적으로 구현된 스레드

소프트웨어적으로 구현된 스레드를 논리적 스레드라고 하겠습니다.
논리적 스레드는 물리적 스레드와 개념이 다릅니다

  • 논리적 스레드 : 프로세스 내에서 실행되는 세부 작업의 단위. 프로세스 실행의 흐름.

논리적 스레드는 물리적 스레드와는 다르게 소프트웨어적으로 얼마든지 할당이 가능합니다. 운영체제가 스케쥴링을 할 때 동시에 실행 가능한 스레드 수(물리적 스레드)는 정해져 있습니다. 하지만 메모리가 허용하는 논리적 스레드 수는 얼마든지 많을 수 있습니다. 이들 중 운영체제에 의해 실행되지 않는 스레드는 잠들어 있을 수 있으며 운영체제는 이들 중 물리적 스레드가 허용 가능한 만큼의 스레드를 할당하여 동시에 실행시킵니다. 책에 비유하자면, 4코어 8스레드는 상/하권으로 분권된 책이 4세트(8권)있는 것과 같습니다. 이를 읽고 싶은 독자(논리적 스레드)는 수십 혹은 수백명이지만 도서관에서 빌릴 수 있는 사람은 최대 8명 입니다. 나머지는 책이 반납될때 까지 기다려야 합니다.

동시성과 병렬성

동시성이란?

  • 싱글 코어에서 멀티 스레드를 동작시키기 위한 방식으로, 멀티 태스킹을 위해 여러 개의 스레드가 번갈아가면서 실행되는 성질을 말한다.
  • 시분할 방식이다.
  • 동시에 실행하는 것 처럼 보이지만, 실제로는 여러 개의 작업을 엄청 빠른 속도로 번갈아가면서 수행하는 것이다.

병렬성이란?

  • 멀티 코어에서 멀티 스레드를 동작시키는 방식, 한 개 이상의 스레드를 포함하는 각 코어들이 동시에 실행하는 성질을 의미한다.
  • 병렬성의 핵심은 물리적인 시간에 동시에 수행되는 것이다. 굳이 멀티 코어가 아니어도 네트워크 상의 여러 컴퓨터에게 분산 작업을 요청하는 분산 컴퓨팅도 병렬성이다.

예제 케이스

각 task 가 수행되는 시간을 1이라고 가정한다.

  • 싱글 코어, 1개의 쓰레드에서 순차적으로 2개의 task 진행 - 동시성과 병렬성 모두 만족하지 못함. seqeuncial 한 작업. 총 수행시간은 2
  • 싱글 코어, 1개의 쓰레드에서 2개의 task 가 자원을 interleaving 하며 진행 - 동시성을 만족하지만 병렬성을 만족하지 못함. 총 수행 시간은 2 + @ (있을수도 없을 수도 있다. interleaving 코스트)
  • 싱글 코어, 2개의 쓰레드에서 2개의 task 가 자원을 interleaving 하며 진행 - 동시성을 만족하지만 병렬성은 만족하지 못함. 총 수행 시간은 2보다 작다.
  • 멀티 코어, 2개의 쓰레드에서 2개의 task 가 동시에 진행 - 동시성, 병렬성을 모두 만족함. 총 수행 시간은 2보다 작다.
  • (보너스) 코틀린 내에서 싱글 코어, 1개의 쓰레드내에서 2개의 코루틴을 통해 2개의 task 가 진행 - 동시성은 만족하지만 병렬성은 만족하지 못함. 총 수행 시간은 2보다 작으며, 2개의 쓰레드를 사용했을 때보다 코스트가 낮다.


코루틴

코루틴이란?

실행을 일시 중단하고 재개할 수 있도록 해서 비선점형 멀티태스킹을 위한 서브 루틴을 일반화하는 컴퓨터 프로그램 구성 요소, 코루틴을 사용하면 스레드를 중단하지 않으면서 코드를 실행할 수 있다.

비선점형 멀티태스킹과 서브 루틴에 대해 알아보자.

비선점형 vs 선점형

OS의 스케줄링을 공부하다보면 선점(preemptive)이라는 단어를 마주하게 된다. CPU와 같은 컴퓨터의 한정적인 자원을 이용해서 여러 개의 태스크(프로세스 혹은 스레드)를 동시에 실행하기 위해서는 자원을 어떻게 분할하여 사용할지에 대한 정책이 필요하다. 스케줄링은 이러한 정책을 정의한다. 즉 처리할 일들의 진행순서를 정하는 것이다.

  • 비선점형 스케줄링
    어떤 프로세스가 CPU를 할당 받으면 그 프로세스가 종료되거나 입출력 요구가 발생하여 자발적으로 중지될 때까지 계속 실행되도록 보장한다. 순서대로 처리되는 공정성이 있고 다음에 처리해야 할 프로세스와 관계없이 응답 시간을 예상할 수 있으며 선점 방식보다 스케줄러 호출 빈도가 낮고 문맥 교환(Context Switching)에 의한 오버헤드가 적다.

  • 선점형 스케줄링
    어떤 프로세스가 CPU를 할당받아 실행 중에 있어도 스케줄러가 실행 중인 프로세스를 강제로 중지하고 다른 프로세스에게 CPU를 할당 할 수 있다. 모든 프로세스에게 CPU 사용 시간을 동일하게 부여할 수 있다.

스레드는 선점형 방식이다. 여러개의 스레드는 CPU 스케줄링의 관리 아래에서 협력적으로 동작한다. 하지만 코루틴은 비선점형 방식이기 때문에 스레드 내에서 자발적인 지연과 재개를 통해 협력적으로 동작한다. CPU 스케줄링에 직접적인 영향을 받지 않기 때문에 지연과 재개가 필요한 것이다.

서브 루틴

서브루틴은 반복되는 특정 기능을 별도로 묶어 놓아 이름을 붙인 것으로 보통 함수나 메서드라고 불린다. 서브루틴은 호출될 때마다 저장된 메모리로 이동했다가 return 을 통해 다시 원래 호출자의 위치로 돌아가게된다.

서브 루틴은 루틴에 진입하는 지점과 루틴을 빠져나오는 지점이 명확하다. 즉, 메인 루틴이 서브 루틴을 호출하면, 서브 루틴의 맨 처음 부분에 진입하여 return 문을 만나거나 서브 루틴의 닫는 괄호를 만나면 해당 서브 루틴을 빠져나오게 된다.

코루틴은 진입할 수 있는 진입점도 여러개고, 함수를 빠져나갈 수 있는 탈출점도 여러개다. 즉, 코루틴 함수는 꼭 return문이나 마지막 닫는 괄호를 만나지 않더라도 언제든지 중간에 나갈 수 있고, 언제든지 다시 나갔던 그 지점으로 들어올 수 있다.

코루틴 vs 스레드

  • 코틀린 코루틴
    기본적으로는 협력형이며 병렬적으로 동작하지 않는다. (옵션을 통해서 여러개의 스레드로 분할하여 병렬적으로 동작하게 할 수 있다.)
    스케줄러가 실행시점을 결정하는 것이 아닌 프로그래머나 이벤트에 의해 실행 및 지연(Suspend), 재개(Resume) 시점이 결정된다.
    비선점형 멀티태스크, 동시성(Concurrency)을 제공한다.

  • 스레드
    CPU 수에 따라서 완전히 병렬적으로 동작할 수 있다.
    OS의 스케줄러가 실행 시점을 결정한다. (스케줄러가 선점한다.)
    선점형 멀티태스크, 멀티프로세싱, 병행성을 제공한다.
    스레드별 독립적인 스택을 가진다.

참고 자료

https://vagabond95.me/posts/concurrency_vs_parallelism/
https://the-boxer.tistory.com/24
https://onlyfor-me-blog.tistory.com/465
https://wooooooak.github.io/kotlin/2019/08/25/%EC%BD%94%ED%8B%80%EB%A6%B0-%EC%BD%94%EB%A3%A8%ED%8B%B4-%EA%B0%9C%EB%85%90-%EC%9D%B5%ED%9E%88%EA%B8%B0/
https://jongmin92.github.io/2021/03/21/Kotlin/coroutines/

Categories:

Updated:

Leave a comment