생활에지혜

멀티태스킹

호사도요 2024. 2. 29. 17:17

멀티태스킹

 

1. 일상 생활에서의 멀티태스킹

 

한 번에 2가지 이상의 일을 동시에 처리하는 것으로 "다중작업" 또는 "다중과업화"라고도 한다.

사람에게도 멀티태스킹(여기서는 다중 업무 처리) 능력을 요구하는 직종이 많은데, 이 경우에는

그냥 여러가지 일을 떠맡기는 꼴이다.

 

중국 촉한의 재상 비의나 조선시대의 류성룡, 르네상스 시기 레오나르도 다빈치 등이 이런 멀티태스킹

능력이 뛰어났다는 일화가 남아 있다.

각각 문서에도 있지만, 그 일화가 공통적으로 바둑을 두면서 정무를 처리했다는 일화라는 게 공통점.

다만, 과도한 멀티태스킹은 두뇌 및 감정에 나쁜 영향을 미친다는 연구 결과가 있다.

, 인간의 두뇌는 멀티태스킹에 맞게 설계되지 않았다는 것이다.

 

그렇기 때문에 멀티 태스킹이라는 것은 실제로 존재하지 않고 우리는 빠른 속도로 태스크 스위칭을 하는

것이라고 한다.

그리고 이런 빠른 태스크 스위칭이 일정 단계를 넘어갈 경우 뇌에 과부하가 걸려 일의 진행 속도와 정확도를

낮추고 빠른 태스크 스위칭에 익숙해진 뇌는 기억력과 집중력이 떨어진다고 한다.

 

 

2. 컴퓨터에서의 멀티태스킹

 

행위자가 사람이 아닌 컴퓨터라는 점만 제외하면 사전적인 의미는 위의 항목과 같다.

최초의 컴퓨터는 한 번에 하나의 작업만을 처리할 수 있었다.

어떤 프로그램을 실행하고 있을 때 다른 프로그램을 실행하려면 실행 중인 프로그램의 작업이 끝나야 다른 작업을

수행할 수 있는 블로킹 방식이었기 때문. 채팅 프로그램으로 비유하면 무전기처럼 채팅해야 하는 셈. 프로세서와

운영체제 기술이 발달하면서 한 번에 여러 가지 작업을 처리할 수 있게 되었다.

Microsoft Windows를 예로 들자면, 동시에 여러 프로그램 창을 띄워서 쓰는 것.

 

현대의 운영체제는 여러 가지 일을 동시에 돌릴 수 있게 하는데, 기본적인 원리는 단순하다.

한 가지 일을 하다가, 잠시 멈추고 또 다른 일을 하고, 또 멈추고 다른 일을 하다 보면 언젠가는 결국 모든 일을

마치게 된다.

이 동작이 엄청 빨라지면 한 번에 여러 가지 일을 하는 것처럼 보이게 되는 것이다.

그림 여러 장을 그려놓고 빠르게 연속 재생하면 눈에 잔상이 남아 그것이 움직여 보이는 것처럼, 한 개체가 여러 가지

동작을 매우 빠르게 하면 그것이 분신술처럼 보이게 되는 것이 바로 멀티태스킹의 원리이다.

유저 프로그램들은 마치 동시에 실행되는 것처럼 보이지만, 커널 내부에서는 운영체제가 각각의 프로그램에 CPU 사용

권을 적절히 분배하는 작업이 반복되고 있다.

하드웨어 자원은 한정되어 있는데 멀티태스킹을 위해 더 많은 작업을 바쁘게 수행해야 하므로 어느 특정 프로그램 하나가 실행할 때 다른 여러 프로그램들과 함께 실행할 때가 실행하지 않을 때보다 더 느릴 수밖에 없지만, 블로킹 상태를 자주

보면서 작업하는 것보단 훨씬 나은 UX를 제공할 수 있기 때문에 멀티태스킹이 정착하게 된 것이다.

보다 효율적인 멀티태스킹이 되기 위해서는 프로세스들을 적절히 분배하는 작업이 이루어져야 하는데 이러한 작업을 프로세스 스케줄링이라고 한다.

 

참고로 최신 리눅스 커널의 경우 보통 한 프로세스에 4ms(4/1000)CPU 사용권을 부여한다고 한다.

밀리초 단위라서 짧게 느껴질지도 모르겠지만, 3~5 GHz 정도의 속도로 동작하는 요즘 일반 데스크탑용 CPU4ms

12백만~2천만 번 정도의 클럭 사이클을 만들어서 최소 수 백만 번 이상의 연산을 수행할 수 있다.

사람으로 치면 4년이라는 매우 긴 시간을 부여하는 것이다.

 

어찌 보면 사람의 약점을 이용한 원리로 보이지만, 사람의 약점만을 이용한 것은 아니다.

모든 컴퓨터 프로그램의 작업이 CPU만을 통하는 것이 아니고 CPU의 명령에 의해 작동하는 다른 장치의 작업이 처리

되는데 필요한 시간도 있는데다 CPU를 거치지 않는 작업도 있기 때문에 필연적으로 멀티태스킹이 아닌 단일 작업만을

처리하는 상황이라도 CPU의 유휴 상황은 발생하게 된다.

마치 네트워크 회선과 공유기의 관계처럼 이용률을 높이는 효과도 있는 것.

 

하지만, 과거의 멀티태스킹은 프로세스 단위로 멀티태스킹하는 '멀티프로세싱'이었는데 이러한 방식은 하드웨어 자원의 부담이 크기 때문에 아무리 잘 스케줄링 해도 한계가 있다.

하드웨어 자원의 부담을 줄이기 위해 프로세스보다 더 작은 실행 단위인 스레드가 도입되었으며, 각 스레드들이 작업

(태스크) 단위로 수행하기 때문에 스레드별로 잘 분배하도록 스케줄링 되면 멀티스레딩이 멀티프로세싱보다 더 나은

멀티태스킹 효율을 보여줄 수 있다.

 

여기서 멀티 CPU나 멀티코어 CPU의 경우 CPU의 코어 개수만큼 더 많은 스레드들의 작업이 동시에 이루어질 수 있다.

이렇게 멀티스레드로 작업을 수행하는 것을 줄여서 '멀티스레딩'이라고도 부르는데, 코어 1개일 때보다 더 많은 스레드로 멀티스레딩 할 수 있다고 해도 일반적으로 2~8개의 코어로는 당연히 수십~수백 개의 프로세스를 모두 처리하지 못하므로 각 CPU 코어에서도 작업을 교체하는 일이 수시로 벌어진다. 물론 n개 코어에서 n개의 프로세스가 동시에 실행되긴 하므로 잘만 하면 멀티 코어를 통해 성능을 끌어올릴 수 있다.

, 일감을 적절히 여러 프로세스에 분배하여 돌리면 이론적으로는 여러 개의 코어를 동시에 사용할 수 있으므로 실제로

성능 향상을 가져온다.

이를 위해서는 프로그래밍 시 멀티 코어를 활용하기 위한 멀티스레드의 적절한 병행화와 병렬화 설계가 필요하다.

그렇지 않으면 코어 하나만 미칠 듯이 돌아가고 나머지 코어들은 시답잖은 프로세스들을 깨작깨작 처리할 뿐이다.

 

그러나 멀티스레드를 이용한 병행 처리와 병렬 처리는 직접 구현하기 까다로운데, 스레드 여러 개 만든다고 해서 사용자가 원하는 멀티스레딩이 자동으로 이루어지는게 아니므로 여러 개의 스레드들을 어떻게 동작시키고 통제할 것인지를 고민해야 하며, 그렇게 고민을 하나하나 해결하다보면 소스코드의 길이가 싱글스레드일 때보다 더 길고 복잡해질 수밖에 없다.

그런 어려움을 해소하기 위해 병행 처리용 라이브러리나 병렬 처리용 라이브러리를 이용하면 비교적 간단한 소스코드의 길이로 구현할 수 있고, 프로그래밍 언어 차원에서 이를 구현해주는 표준 라이브러리가 없을 경우 OpenMP, TBB, PPL 등의 외부 라이브러리를 가져와서 구현할 수 있다.

하지만 소스코드의 길이가 길든 짧든 적용할 수 있는 부분은 순서에 관계없는 단순한 반복 작업들을 동시에 처리할 경우에나 고려하는 정도로 한정적이다.

그리고 멀티코어 프로세서 환경을 고려하여 여러 프로세스들에게 일감을 적절히 싣더라도, 여러 개 코어를 쓴다고 해서

프로그램 실행 속도가 코어 개수만큼 빨라지지는 않는다.

가장 큰 이유는 모든 작업을 '100% 동시에 처리할 수는 없기 때문이다. 예를 들어, A라는 작업을 수행하는 데 B라는 선행 작업의 결과가 필요하다면, 필연적으로 B를 먼저 수행한 후에만 A를 수행할 수 있다.

AB를 같이 돌려 봤자, AB가 끝나기 전까지 기다릴 수밖에 없다.

때문에 작업에 따라서 멀티태스킹으로 인한 효율이 프로그램의 로직에 따라 천차만별이다.

 

실행 중인 프로그램(정확히는 프로세스) 내부의 여러 스레드끼리 멀티스레딩 하는 것도 넓은 의미로는 멀티스레드를 이용한 일종의 멀티태스킹으로 볼 수도 있지만 컴퓨터 멀티태스킹의 유래가 서로 다른 실행 프로그램들을 동시에 처리하는 것에서 출발했던 개념이라 프로세스 내부의 병행 처리, 병렬 처리하는 형태는 행위자인 연산 장치 입장에서는 병행 컴퓨팅와 병렬 컴퓨팅, 프로그래머 입장에서는 병행 프로그래밍과 병렬 프로그래밍이라는 용어로 따로 취급하는 편이다.

 

굳이 집합 기호로 표현하면 '병렬 처리 병행(동시) 처리 프로세스 내부의 멀티스레딩 운영체제 차원의

멀티스레딩 멀티태스킹'인 셈.

 

또한, 멀티스레딩의 속도 증가치가 스레드 개수만큼 정비례하게 증가하지 않는 이유는 운영체제가 한 프로세스를 처리

하다가 다른 프로세스로 넘어갈 때 컨텍스트 스위칭(문맥 교환)이라는 작업이 수반되면서 발생하는 오버헤드 때문이다. , 바로 다른 프로세스로 바꿀 수 있는게 아니라, 중간에 작업 전환을 하는데도 시간이 필요하다는 이야기. 각각의 프로

세스는 자신이 사용하고 있는 컴퓨터의 자원 들이 있는데 프로세스 전환 시 사용 중인 자원들도 전환해야 한다.

물론 데이터를 버릴 수는 없으니 작업 중인 데이터를 저장하고, 다른 프로세스에서 쓸 데이터를 메모리에서 가져오는데

시간이 걸린다. CPU 아키텍처 및 운영체제, 메모리 사용량에 따라 다르지만 대개 몇백 ns에서 몇 μs 정도의 시간이 걸린다고 보면 된다. 이러한 전환 작업은 사람이 전혀 느낄 수 없을 정도로 짧고 유저 프로그램에게조차도 짧은 시간이지만,

커널 개발자나 60FPS을 뽑아야 할 정도로 퍼포먼스에 민감한 고사양 게임을 개발하는 렌더링 프로그래머에게는 꽤 비싼 작업으로 여겨지는 듯. 물론 멀티 프로세스를 기반으로 하는 서버에서나 고려해볼만한 상황이고 유저 입장에서는 찰나라고 봐도 될 정도로 짧다.

 

물론, 서로 다른 작업을 동시에 처리하는 것이 아니라 똑같은 작업들을 동시에 처리해야 할 경우, 스레드별로 분담해서

스레드끼리 서로 영향을 주지 않고 각 스레드에게 주어진 작업만 처리하도록 프로그래밍 하면 최소한 그 구간만큼은

스레드끼리 컨텍스트 스위칭 할 필요가 없어져 오버헤드가 크지 않게 되는데 병렬 처리가 이에 해당된다.

하지만 똑같은 일이라도 스레드마다 처리 속도가 들쭉날쭉하기 때문에 이를 안정적으로 동작하기 위해 가장 오래 걸리는 스레드의 처리 완료 시간에 맞춰서 배리어 락을 걸다보면 일찍 처리 완료된 스레드의 대기 시간 발생이 불가피해지므로

걸리는 시간이 스레드 개수만큼 나누어진 시간으로 되지 못 하는 단점이 있다.

대기 시간으로 인한 전체 처리 시간의 지연을 줄이기 위해 이미 처리 완료된 스레드가 처리가 더디는 스레드의 남은 일을 훔쳐서 처리해주는 '태스크 스틸링', 더 나아가면 '종속성 그래프' 방식을 통해 보완할 수 있지만 실제로 그렇게까지 활용

하는 곳은 많지 않고 제대로 병렬화 해봤자 태스크 스틸링까지 구현하는 경우가 대부분이다.

프로그램에 따라 다르지만 종속성 그래프를 구현해야 할 정도는 비교적 극단적인 경우인데다 구현하기가 복잡해서 안

그래도 어려운 멀티스레딩에서 더 어려워지므로, 태스크 스틸링까지만 구현해도 CPU의 모든 코어 자원을 대부분 점유

할 수 있다.

 

멀티태스킹에는 두 종류가 있는데, 첫 번째는 비선점형 멀티태스킹, 두 번째는 선점형 멀티태스킹이다.

 

프로그램은 실행되면 프로세스가 되고 프로세스는 역시 여러 쓰레드를 실행시키는데 여러 프로그램에서 만들어지는 이

멀티쓰레드는 CPU라는 한정된 자원을 서로 사용하고자 경쟁 관계를 가진다.

그러므로 운영체제는 여러 쓰레드들에게 뒤죽박죽 개판 5분 전 되지 않도록 CPU의 시간을 나누어 돌아가며 실행하도록 하는데, 이 때 CPU를 차지하고 있는 쓰레드가 자신이 이제 CPU 연산이 필요 없음을 나타냈을 때에만 운영체제가 이를

회수할 수 있는 경우를 비선점형 멀티태스킹이라고 하고, 프로세스가 CPU를 차지해서 사용하더라도 운영체제가 타이머나 여타 트리거를 통해 개입하여 강제로 CPU 사용을 빼앗아 올 수 있는 경우를 선점형 멀티태스킹이라고 한다.

 

쉽게 말해 운영체제가 응답없는 프로세스를 강제로 죽이고 자시고 할 수 있으면 선점형, 그게 안 돼서 닥치고 리셋해야만 하는 경우라면 비선점형이다. 선점형 멀티태스킹은 스케줄러에 따라 차이가 지긴 하지만, 원론적으로는 보통 시간을 따로 정해 놓고 이 시간마다 선점(preemption)이 일어나는데, 이 시간 단위를 퀀텀 혹은 슬라이스라 한다. 퀀텀이 너무 낮으면 프로세스 바꾸는데 소모되는 리소스가 커지고, 퀀텀이 너무 높으면 반응 속도가 느려진다.

보통 빠른 타수의 사람이 키를 입력하는 속도가 약 100ms 정도이기 때문에, 퀀텀도 이정도 수준에서 좀더 낮게 결정되는 경향이 있다. 리눅스의 경우 퀀텀을 따로 설정할수도 있긴 하지만, 어차피 리눅스에서 디폴트로 사용하는 CFS 스케쥴러는 상황을 보면서 작동하기 때문에 퀀텀대로만 선점을 하지는 않는다.

 

현행 대부분의 OS, Microsoft Windows, 리눅스, OS X 등은 모두 선점형 멀티태스킹인데 이유를 생각하면 당연하다. 범용 운영체제인 만큼 여러 프로그램들을 실행시켜야 할텐데 그 프로그램들은 모두 검증된 프로그램이 아니고 버그도 갖고 있다. 만약 어떤 프로그램이 이러한 이유로 자원을 가진 채로 버그에 빠지거나 자원을 독식하려 한다면 멀티태스킹이 제대로 이루어지지 않을 것이다. 다만 Windows 95에서는 16비트 프로그램에서는 비선점형 멀티태스킹으로 작동하는데 이는 하위 호환성을 위해 운영체제 구조상 어쩔 수 없었던 부분이다. 기존 16비트 시절의 Windows(1.0~3.1)가 비선점형으로 만들어졌기 때문. 참고로 OS/216비트 Windows 프로그램도 선점형으로 돌린다.

 

MS-DOS의 경우 운영체제에서 아무런 멀티태스킹 및 멀티스레드 기능을 지원하지 않는다. 싱글CPU, 싱글 코어, 싱글 스레드에서 모든 처리가 동작한다는 가정 하에 동작하며, DOS 상에서 동작하는 램 상주 프로그램 등은 CPU 자체에서 핀을 통한 입력으로 지원하는 인터럽트 벡터 테이블(interrupt vector table)을 수정하여 '잠시 CPU 처리를 스톱시키고 다른

일을 했다가 돌려놓는' 방식으로 직접 프로그래밍하여 작동한다.

 

프로세스의 스케줄링을 구현하는데도 여러가지 알고리즘이 존재한다. 리눅스에서는 O(1) 스케쥴러가 사용되다가 2.6.23 버전부터 CFS(Completely Fair Scheduler)가 도입되었다.

 

모바일 운영체제인 iOS에선 패스트 스위칭과 멀티태스킹이 공존하는 형태이다. 자세한 내용은 해당 문서 참조.

 

다른 모바일 운영체제인 안드로이드는 리눅스 커널을 바탕으로 했으니 당연히 지원한다. iOS와 달리 안드로이드

누가부터 멀티 윈도우를 정식으로 지원한다.

'생활에지혜' 카테고리의 다른 글

'템플스테이' 절반 비용으로  (2) 2024.03.08
아파트 화재 시 대피 방법  (0) 2024.03.08
서울시민의 금융생활  (1) 2024.02.26
현대판 처세술  (0) 2024.02.14
교통 안내  (0) 2024.02.13