스레드(Thread) 개요
스레드(Thread)
: CPU 이용의 기본 단위- 구성 → 스레드 ID + 프로그램 카운터(PC) + 레지스터 집합 + 스택
- 같은 프로세스에 속한 다른 스레드와 운영체제 자원들을 공유
- 운영체제 자원들 → 코드, 데이터 섹션, 열린 파일이나 신호 같은 것
- 운영체제 자원들 → 코드, 데이터 섹션, 열린 파일이나 신호 같은 것
- 2가지의 스레드
단일 스레드 프로세스
: 전통적인 프로세스로, 하나의 제어 스레드를 가지고 있다.- 한 번에 하나의 작업만 수행할 수 있음
- 한 번에 하나의 작업만 수행할 수 있음
다중 스레드 프로세스
: 하나의 프로세스가 다수의 제어 스레드를 가지고 있음- 동시에 하나 이상의 작업을 수행할 수 있다.
- 동시에 하나 이상의 작업을 수행할 수 있다.
동기(Motivation)
- 현대의 거의 모든 소프트웨어 응용들은 다중 스레드를 이용한다.
- 하나의 응용은 몇 개의 실행 흐름을 가진 독립적인 프로세스로 구현된다.
- 예
- 워드에서 그래픽을 표시하는 스레드, 사용자 키 입력에 응답하는 스레드가 따로 있다.
- 웹 브라우저는 하나의 스레드가 이미지를 표시하고 다른 스레드는 네트워킹을 할 수 있다.
- 예
- 응용은 다중 코어 시스템에서 처리 능력을 향상하도록 설계될 수 있다.
- 응용은 다중 계산 코어를 사용하여 다수의 CPU-집중 작업을 병렬로 처리할 수 있다.
- 하나의 응용은 몇 개의 실행 흐름을 가진 독립적인 프로세스로 구현된다.
웹 서버에서의 다중 스레드 사용
- 만약 웹 서버가 단일 스레드 프로세스로 작동한다고 가정
→ 단일 프로세스가 한 번에 하나의 클라이언트만 서비스 가능
→ 클라이언트는 자신의 요구가 서비스되기까지 매우 긴 시간을 기다려야 함 - 해결책
- 서버에게 요청이 들어오면, 프로세스는 그 요청을 수행할 별도의 프로세스를 생성하는 방식
- 스레드가 대중화되기 전엔 보편적이었던 방식
- 프로세스 생성 작업은 매우 많은 시간과 자원 소모
- → 새 프로세스와 기존 프로세스가 동일한데 굳이 만드는 것은 비효율적
- 프로세스 안에 여러 스레드를 만드는 방식 → 더 효율적인 방식
- 서버는 클라이언트의 요청을 listen 하는 별도의 스레드를 생성
- 요청이 들어오면 다른 프로세스를 생성하는 것이 아님.
- 요청을 서비스할 새로운 스레드를 생성함과 동시에
추가적인 요청을 listen 하기 위한 작업을 재개
- 요청을 서비스할 새로운 스레드를 생성함과 동시에
- 서버에게 요청이 들어오면, 프로세스는 그 요청을 수행할 별도의 프로세스를 생성하는 방식
Linux 시스템에서의 다중 스레드
- Linux 시스템에서 시스템을 부트 하는 동안 여러 커널 스레드가 생성
- 대부분의 운영체제 커널도 일반적으로 다중 스레드
- 각 스레드는 장치 관리, 메모리 관리 또는 인터럽트 처리와 같은 특정 작업 수행
ps -ef
명령을 사용하여 실행 중인 Linux 시스템에서 커널 스레드를 표시 가능
응용 프로그램에서의 다중 스레드
- 많은 응용 프로그램에서 기본 정렬, 트리 및 그래프 알고리즘을 포함하여 다중 스레드를 활용 가능
- 데이터 마이닝, 그래픽 및 인공지능에서 CPU 중심의 최신 문제를 해결해야 하는 프로그래머
→ 병렬로 실행되는 설루션을 설계하여 최신 다중 코어 시스템의 성능 활용 가능
장점
- 다중 스레드 프로그래밍 이점은
응답성
자원 공유
경제성
규모 적응성
4가지로 나눌 수 있음
1. 응답성(responsiveness)
- 대화형 응용을 다중 스레드 화하면 사용자에 대한 응답성을 증가시킨다.
- 응답성을 증가시키는 이유
- 응용 프로그램의 일부분이 봉쇄되거나, 긴 작업을 수행하더라도, 프로그램의 수행이
계속되는 것을 허용하기 때문
- 응용 프로그램의 일부분이 봉쇄되거나, 긴 작업을 수행하더라도, 프로그램의 수행이
- 응답성을 증가시키는 이유
- 해당 특징은 사용자 인터페이스를 설계하는 데 있어 특히 유용
- 예 : 사용자 시간이 많이 걸리는 연산을 시작하는 단추를 클릭했을 때
- 단일 스레드 응용 → 그 연산이 완료될 때까지 사용자가 응답하지 않음
- 별도의 비동기적 스레드 → 응용은 여전히 사용자에게 응답 가능
- 예 : 사용자 시간이 많이 걸리는 연산을 시작하는 단추를 클릭했을 때
2. 자원 공유(resource sharing)
- 스레드는 자동으로 자신들이 속한 프로세스의 자원들과 메모리를 공유 → 코드와 데이터를 공유
- cf ) 프로세스는 공유 메모리와 메시지 전달 기법을 통해서만 자원 공유 가능
- cf ) 프로세스는 공유 메모리와 메시지 전달 기법을 통해서만 자원 공유 가능
- 코드와 데이터 공유의 이점
- 한 응용 프로그램이 같은 주소 공간 내에 여러 개의 다른 작업을 하는 스레드를 가질 수 있음
3. 경제성(economy)
- 스레드를 생성하고 문맥 교환하는 것은 더욱 효과적이다.
← 스레드는 자신이 속한 프로세스의 자원들을 공유하기 때문에 - 스레드 생성은 프로세스 생성보다 시간과 메모리를 덜 소비한다.
- 문맥 교환(context switching)은 프로세스 사이보다 스레드 사이에서 더 빠르다.
4. 규모 적응성(scalalbility)
- 다중 스레드의 이점은 다중 처리기 구조에서 더욱 증가
← 다중 처리기 구조에서는 각각의 스레드가 다른 처리기에서 병렬로 수행될 수 있기 때문- 단일 스레드 프로세스는 처리기가 아무리 많아도 오직 한 처리기에서만 실행됨
다중 코어 프로그래밍
다중 코어
: 단일 컴퓨팅 칩에 여러 컴퓨팅 코어를 배치하는 것- 각 코어는 운영체제에 별도의 CPU를 가지고 있음
각 코어 시스템에 따른 병행 실행
- 다중 스레드 프로그래밍은 컴퓨팅 코어를 보다 효율적으로 사용하고 병행성을 향상하는 기법 제공
- 스레드가 4개인 응용 프로그램이라고 가정
- 단일 컴퓨팅 코어가 있는 시스템의 경우
- 인터리브(사이사이에 끼워 넣는 것)되게 실행
- 인터리브(사이사이에 끼워 넣는 것)되게 실행
- 다중 컴퓨팅 코어가 있는 시스템의 경우
- 일부 스레드가 병렬로 실행될 수 있음을 의미
← 병행성은 시스템이 각 코어에 별도의 스레드를 할당할 수 있기 때문
- 일부 스레드가 병렬로 실행될 수 있음을 의미
- 단일 컴퓨팅 코어가 있는 시스템의 경우
병행성 vs 병렬성
병행성
: 병행 시스템은 모든 작업이 진행되게 하여 둘 이상의 작업을 지원하는 것- 동시에 진행하는 것이 아닌 두 작업을 번갈아가면서 진행하는 것을 의미
- 동시에 진행하는 것이 아닌 두 작업을 번갈아가면서 진행하는 것을 의미
병렬성
: 병렬 시스템은 둘 이상의 작업을 동시에 수행하는 것- 단일 프로세서 → 병렬성 없이 병행성만 가질 수 있다.
프로그래밍 도전과제
- 다중 코어 시스템으로의 발전은 응용 프로그래머에게도 다중 코어의 활용도를 높이도록 압박을 줌
- 운영체제 설계자는 병렬 수행은 위한 여러 코어를 활용하는 스케줄링 알고리즘을 개발해야 함
- 운영체제 설계자는 병렬 수행은 위한 여러 코어를 활용하는 스케줄링 알고리즘을 개발해야 함
- 응용 프로그래머는 기존 프로그램을 다중 스레드를 사용하도록 수정
및 다중 스레드 프로그램을 설계해야 하는 도전에 당면해 있음 - 다중 코어 시스템을 위한 프로그래밍 도전과제는 5개가 존재
태스크 인식(identifying tasks)
- 응용을 분석하여 독립된 병행 기능 태스크로 나눌 수 있는 영역을 찾는 작업이 필요
- 태스크는 서로 독립적이고 따라서 개별 코어에서 병렬 실행될 수 있어야 한다.
균형(balance)
- 전체 작업에 균등한 기여도를 가지도록 태스크를 나누는 것도 중요하다.
- 어떤 경우에는 다른 태스크에 비해 기여도가 적은 작업이 있을 수 있음
→ 이런 작업에 별도의 코어를 사용하는 것은 낭비
- 어떤 경우에는 다른 태스크에 비해 기여도가 적은 작업이 있을 수 있음
- 전체 작업에 균등한 기여도를 가지도록 태스크를 나누는 것도 중요하다.
데이터 분리(data spliting)
- 태스크가 접근하고 조작하는 데이터는 개별 코어에서 사용할 수 있도록 나누어져야 한다.
- 응용이 독립된 태스크로 나누어지는 것과 비슷
- 응용이 독립된 태스크로 나누어지는 것과 비슷
- 태스크가 접근하고 조작하는 데이터는 개별 코어에서 사용할 수 있도록 나누어져야 한다.
데이터 종속성(data dependency)
- 태스크가 접근하는 데이터는 둘 이상의 태스크 사이에 종속성이 없는지 검토되어야 한다.
- 종속적인 경우
→ 프로그래머가 데이터 종속성 수용을 위해 태스크의 수행을 잘 동기화해야 함.
- 종속적인 경우
- 태스크가 접근하는 데이터는 둘 이상의 태스크 사이에 종속성이 없는지 검토되어야 한다.
시험 및 디버깅(testing and debugging)
- 병행 프로그램을 시험하고 디버깅하는 것은 단일 스레드 응용보다 훨씬 어렵다.
← 프로그램이 다중 코어에서 병렬로 실행될 때, 다양한 실행 경로로 존재할 수 있기 때문
- 병행 프로그램을 시험하고 디버깅하는 것은 단일 스레드 응용보다 훨씬 어렵다.
병렬 실행의 유형 - 2가지 유형 존재
데이터 병렬 실행
- 동일한 데이터의 부분집합을 다수의 계산 코어에 분배 한 뒤, 각 코어에서 동일한 연산 실행
- 기본적으로 여러 코어에 데이터를 분배하는 것이 포함
- 예시 - 크기가 N인 배열의 내용을 더하는 경우
- 코어 0은 [0 ~ N/2 -1]까지 더하고, 코어 1은 [N/2 ~ N]까지 더함
- 코어 0은 [0 ~ N/2 -1]까지 더하고, 코어 1은 [N/2 ~ N]까지 더함
태스크 병렬 실행
- 데이터가 아닌 태스크(스레드)를 다수의 코어에 분배. 각 스레드는 고유의 연산을 실행
- 다른 스레드들이 동일한 데이터에 대해 연산을 실행하거나,
서로 다른 데이터에 대해 연산을 실행할 수도 있다.
- 다른 스레드들이 동일한 데이터에 대해 연산을 실행하거나,
- 기본적으로 여러 코어에 태스크를 분배하는 것이 포함
- 예시 - 크기가 N인 배열의 내용을 더하는 경우
- 각자 고유한 통계 연산을 수행하는 2개의 스레드가 필요할 수 있음
- 이 스레드들은 개별 코어에서 병렬로 실행되지만, 각각 고유한 연산을 실행
- 데이터가 아닌 태스크(스레드)를 다수의 코어에 분배. 각 스레드는 고유의 연산을 실행
- 데이터와 태스크 병렬 처리는 상호 배타적이지 않으며, 이 두 가지 전략을 혼합하여 사용 가능