호우동의 개발일지

Today :

article thumbnail

스레드(Thread) 개요

  • 스레드(Thread) : CPU 이용의 기본 단위
    • 구성 → 스레드 ID + 프로그램 카운터(PC) + 레지스터 집합 + 스택
    • 같은 프로세스에 속한 다른 스레드와 운영체제 자원들을 공유
      • 운영체제 자원들 → 코드, 데이터 섹션, 열린 파일이나 신호 같은 것

  • 2가지의 스레드
    • 단일 스레드 프로세스 : 전통적인 프로세스로, 하나의 제어 스레드를 가지고 있다.
      • 한 번에 하나의 작업만 수행할 수 있음
        단일 스레드 프로세스 구조
        단일 스레드 프로세스 내부 구조
    • 다중 스레드 프로세스 : 하나의 프로세스가 다수의 제어 스레드를 가지고 있음
      • 동시에 하나 이상의 작업을 수행할 수 있다.
        단일 스레드 프로세스 내부 구조
        단일 스레드 프로세스 내부 구조

 


동기(Motivation)

  • 현대의 거의 모든 소프트웨어 응용들은 다중 스레드를 이용한다.
    • 하나의 응용은 몇 개의 실행 흐름을 가진 독립적인 프로세스로 구현된다.
        • 워드에서 그래픽을 표시하는 스레드, 사용자 키 입력에 응답하는 스레드가 따로 있다.
        • 웹 브라우저는 하나의 스레드가 이미지를 표시하고 다른 스레드는 네트워킹을 할 수 있다.

    • 응용은 다중 코어 시스템에서 처리 능력을 향상하도록 설계될 수 있다.
      • 응용은 다중 계산 코어를 사용하여 다수의 CPU-집중 작업을 병렬로 처리할 수 있다.

 


웹 서버에서의 다중 스레드 사용

  • 만약 웹 서버가 단일 스레드 프로세스로 작동한다고 가정
    → 단일 프로세스가 한 번에 하나의 클라이언트만 서비스 가능
    → 클라이언트는 자신의 요구가 서비스되기까지 매우 긴 시간을 기다려야 함

  • 해결책
    1. 서버에게 요청이 들어오면, 프로세스는 그 요청을 수행할 별도의 프로세스를 생성하는 방식
      • 스레드가 대중화되기 전엔 보편적이었던 방식
      • 프로세스 생성 작업은 매우 많은 시간과 자원 소모
      • 새 프로세스와 기존 프로세스가 동일한데 굳이 만드는 것은 비효율적

    2. 프로세스 안에 여러 스레드를 만드는 방식 → 더 효율적인 방식
      다중 스레드 서버 구조
      다중 스레드 서버 구조
      • 서버는 클라이언트의 요청을 listen 하는 별도의 스레드를 생성
      • 요청이 들어오면 다른 프로세스를 생성하는 것이 아님.
        • 요청을 서비스할 새로운 스레드를 생성함과 동시에
          추가적인 요청을 listen 하기 위한 작업을 재개

 


Linux 시스템에서의 다중 스레드

  • Linux 시스템에서 시스템을 부트 하는 동안 여러 커널 스레드가 생성
    • 대부분의 운영체제 커널도 일반적으로 다중 스레드
  • 각 스레드는 장치 관리, 메모리 관리 또는 인터럽트 처리와 같은 특정 작업 수행
  • ps -ef 명령을 사용하여 실행 중인 Linux 시스템에서 커널 스레드를 표시 가능

 


응용 프로그램에서의 다중 스레드

  • 많은 응용 프로그램에서 기본 정렬, 트리 및 그래프 알고리즘을 포함하여 다중 스레드를 활용 가능
  • 데이터 마이닝, 그래픽 및 인공지능에서 CPU 중심의 최신 문제를 해결해야 하는 프로그래머
    → 병렬로 실행되는 설루션을 설계하여 최신 다중 코어 시스템의 성능 활용 가능

 


장점

  • 다중 스레드 프로그래밍 이점은 응답성 자원 공유 경제성 규모 적응성 4가지로 나눌 수 있음

 

1. 응답성(responsiveness)

  • 대화형 응용을 다중 스레드 화하면 사용자에 대한 응답성을 증가시킨다.
    • 응답성을 증가시키는 이유
      • 응용 프로그램의 일부분이 봉쇄되거나, 긴 작업을 수행하더라도, 프로그램의 수행이
        계속되는 것을 허용하기 때문

  • 해당 특징은 사용자 인터페이스를 설계하는 데 있어 특히 유용
    • 예 : 사용자 시간이 많이 걸리는 연산을 시작하는 단추를 클릭했을 때
      • 단일 스레드 응용 → 그 연산이 완료될 때까지 사용자가 응답하지 않음
      • 별도의 비동기적 스레드 → 응용은 여전히 사용자에게 응답 가능

 

2. 자원 공유(resource sharing)

  • 스레드는 자동으로 자신들이 속한 프로세스의 자원들과 메모리를 공유 → 코드와 데이터를 공유
    • cf ) 프로세스는 공유 메모리와 메시지 전달 기법을 통해서만 자원 공유 가능

  • 코드와 데이터 공유의 이점
    • 한 응용 프로그램이 같은 주소 공간 내에 여러 개의 다른 작업을 하는 스레드를 가질 수 있음

 

3. 경제성(economy)

  • 스레드를 생성하고 문맥 교환하는 것은 더욱 효과적이다.
    ← 스레드는 자신이 속한 프로세스의 자원들을 공유하기 때문에

  • 스레드 생성은 프로세스 생성보다 시간과 메모리를 덜 소비한다.
  • 문맥 교환(context switching)은 프로세스 사이보다 스레드 사이에서 더 빠르다.

 

4. 규모 적응성(scalalbility)

  • 다중 스레드의 이점은 다중 처리기 구조에서 더욱 증가
    ← 다중 처리기 구조에서는 각각의 스레드가 다른 처리기에서 병렬로 수행될 수 있기 때문
    • 단일 스레드 프로세스는 처리기가 아무리 많아도 오직 한 처리기에서만 실행됨

 


다중 코어 프로그래밍

  • 다중 코어 : 단일 컴퓨팅 칩에 여러 컴퓨팅 코어를 배치하는 것
    • 각 코어는 운영체제에 별도의 CPU를 가지고 있음

 

각 코어 시스템에 따른 병행 실행

  • 다중 스레드 프로그래밍은 컴퓨팅 코어를 보다 효율적으로 사용하고 병행성을 향상하는 기법 제공
  • 스레드가 4개인 응용 프로그램이라고 가정
    • 단일 컴퓨팅 코어가 있는 시스템의 경우
      단일코어
      • 인터리브(사이사이에 끼워 넣는 것)되게 실행

    • 다중 컴퓨팅 코어가 있는 시스템의 경우
      다중 코어
      다중 코어
      • 일부 스레드가 병렬로 실행될 수 있음을 의미
        ← 병행성은 시스템이 각 코어에 별도의 스레드를 할당할 수 있기 때문

 

병행성 vs 병렬성

  • 병행성 : 병행 시스템은 모든 작업이 진행되게 하여 둘 이상의 작업을 지원하는 것
    • 동시에 진행하는 것이 아닌 두 작업을 번갈아가면서 진행하는 것을 의미

  • 병렬성 : 병렬 시스템은 둘 이상의 작업을 동시에 수행하는 것
  • 단일 프로세서 → 병렬성 없이 병행성만 가질 수 있다.

 


프로그래밍 도전과제

  • 다중 코어 시스템으로의 발전은 응용 프로그래머에게도 다중 코어의 활용도를 높이도록 압박을 줌
    • 운영체제 설계자는 병렬 수행은 위한 여러 코어를 활용하는 스케줄링 알고리즘을 개발해야 함

  • 응용 프로그래머는 기존 프로그램을 다중 스레드를 사용하도록 수정
    및 다중 스레드 프로그램을 설계해야 하는 도전에 당면해 있음
  • 다중 코어 시스템을 위한 프로그래밍 도전과제는 5개가 존재
    • 태스크 인식(identifying tasks)
      • 응용을 분석하여 독립된 병행 기능 태스크로 나눌 수 있는 영역을 찾는 작업이 필요
      • 태스크는 서로 독립적이고 따라서 개별 코어에서 병렬 실행될 수 있어야 한다.

    • 균형(balance)
      • 전체 작업에 균등한 기여도를 가지도록 태스크를 나누는 것도 중요하다.
        • 어떤 경우에는 다른 태스크에 비해 기여도가 적은 작업이 있을 수 있음
          → 이런 작업에 별도의 코어를 사용하는 것은 낭비

    • 데이터 분리(data spliting)
      • 태스크가 접근하고 조작하는 데이터는 개별 코어에서 사용할 수 있도록 나누어져야 한다.
        • 응용이 독립된 태스크로 나누어지는 것과 비슷

    • 데이터 종속성(data dependency)
      • 태스크가 접근하는 데이터는 둘 이상의 태스크 사이에 종속성이 없는지 검토되어야 한다.
        • 종속적인 경우
          → 프로그래머가 데이터 종속성 수용을 위해 태스크의 수행을 잘 동기화해야 함.

    • 시험 및 디버깅(testing and debugging)
      • 병행 프로그램을 시험하고 디버깅하는 것은 단일 스레드 응용보다 훨씬 어렵다.
        ← 프로그램이 다중 코어에서 병렬로 실행될 때, 다양한 실행 경로로 존재할 수 있기 때문

 


병렬 실행의 유형 - 2가지 유형 존재

  1. 데이터 병렬 실행
    데이터 병렬 실행
    데이터 병렬 실행

    • 동일한 데이터의 부분집합을 다수의 계산 코어에 분배 한 뒤, 각 코어에서 동일한 연산 실행
    • 기본적으로 여러 코어에 데이터를 분배하는 것이 포함
    • 예시 - 크기가 N인 배열의 내용을 더하는 경우
      • 코어 0은 [0 ~ N/2 -1]까지 더하고, 코어 1은 [N/2 ~ N]까지 더함

  2. 태스크 병렬 실행
    태스크 병렬 실행
    태스크 병렬 실행
    • 데이터가 아닌 태스크(스레드)를 다수의 코어에 분배. 각 스레드는 고유의 연산을 실행
      • 다른 스레드들이 동일한 데이터에 대해 연산을 실행하거나,
        서로 다른 데이터에 대해 연산을 실행할 수도 있다.

    • 기본적으로 여러 코어에 태스크를 분배하는 것이 포함
    • 예시 - 크기가 N인 배열의 내용을 더하는 경우
      • 각자 고유한 통계 연산을 수행하는 2개의 스레드가 필요할 수 있음
      • 이 스레드들은 개별 코어에서 병렬로 실행되지만, 각각 고유한 연산을 실행

  • 데이터와 태스크 병렬 처리는 상호 배타적이지 않으며, 이 두 가지 전략을 혼합하여 사용 가능