CPU에서 실행 중이던 프로세스스레드가 다른 것으로 교체되는 것. 컨텍스트란 CPU나 메모리에 남아 있는 그 프로세스의 상태를 말한다. 여러 개를 동시에 실행시키려면 반드시 필요하고, 그때마다 비용을 치른다.

일어나는 시점과 통제하는 쪽

주어진 시간 조각을 다 썼을 때, IO 작업을 해야 할 때, 다른 자원을 기다려야 할 때 일어난다.

실행하는 주체는 언제나 OS 커널이다. 각종 자원을 관리하고 감독하는 쪽이 통제권을 쥐고 교체를 수행한다. 무엇이 유발하는가와 누가 총괄하는가는 다른 질문이다. 유발은 프로세스의 IO 요청일 수 있지만 실제 교체는 커널의 몫이다.

교체할 때 하는 두 가지

교체는 어느 경우든 두 가지를 한다. 첫째로 커널 모드에서 실행된다. 프로세스가 하드웨어나 시스템 자원을 다뤄야 할 때 직접 접근하지 않고 커널을 거치기 때문이다. 둘째로 CPU 레지스터 상태를 교체한다. 레지스터는 명령어를 수행하는 데 필요한 데이터를 담는 곳이라 실행 중에 값이 계속 바뀐다. 나중에 다시 실행될 때 어디까지 했는지 알아야 이어갈 수 있으니 기존 상태를 어딘가에 저장해둔다.

프로세스끼리와 스레드끼리

프로세스끼리의 교체는 가상 메모리 주소 관련 처리를 하나 더 한다. 서로 다른 프로세스는 메모리 주소 체계가 다르기 때문이다. MMU(메모리 관리 장치)가 새 프로세스의 주소 체계를 보도록 고쳐야 하고, 가상 주소와 실제 주소의 매핑을 담아둔 캐시인 TLB도 비워야 한다. 이 작업을 빠뜨리면 새로 올라온 P2가 P1의 메모리 주소로 잘못 접근하는 일이 생긴다.

같은 프로세스의 스레드끼리라면 이 작업이 필요 없다. 메모리 영역을 공유하니 주소 체계가 그대로다. 스레드 전환이 가볍다는 말은 정확히 이 차이를 가리킨다.

캐시 오염

레지스터 말고도 잃는 것이 있다. CPU 캐시에는 직전 프로세스가 쓰던 데이터가 올라와 있는데, 다른 프로세스로 바뀌면 그 데이터가 쓸모없어진다. 원하는 값을 찾으려면 메모리까지 다시 가야 하니 한동안 느리다. 이것을 캐시 오염이라고 부르고, 전환 자체의 비용보다 이쪽이 더 클 수 있다.

순수한 오버헤드

사용자 관점에서 컨텍스트 스위칭은 순수한 오버헤드다. 내가 실행한 프로그램의 동작과 아무 상관 없이 CPU를 잡아먹는 간접비용이다. 코어 수보다 스레드가 많으면 전환이 잦아지고 그만큼 오버헤드가 커지는데, 스레드를 많이 만든다고 빨라지지 않는 이유가 여기 있다. 몇 개가 적당한지는 CPU bound와 IO bound에서 갈린다.

관련

출처