Microsoft MVP성태의 닷넷 이야기
Windows: 280. Hyper-V의 3가지 Thread Scheduler (Classic, Core, Root) [링크 복사], [링크+제목 복사],
조회: 2321
글쓴 사람
정성태 (seongtaejeong at gmail.com)
홈페이지
첨부 파일
 

(시리즈 글이 12개 있습니다.)
Windows: 63. 윈도우 서버 2012 - Hyper-V의 새로운 기능 Live Migration
; https://www.sysnet.pe.kr/2/0/1356

개발 환경 구성: 211. Hyper-V - Generation 2 유형의 VM 생성 시 ISO 부팅이 안된다면?
; https://www.sysnet.pe.kr/2/0/1603

개발 환경 구성: 236. Hyper-V에 설치한 리눅스 VM의 VHD 크기 늘리는 방법
; https://www.sysnet.pe.kr/2/0/1742

개발 환경 구성: 317. Hyper-V 내의 VM에서 다시 Hyper-V를 설치: Nested Virtualization
; https://www.sysnet.pe.kr/2/0/11218

개발 환경 구성: 405. Hyper-V 가상 머신에서 직렬 포트(Serial Port, COM Port) 사용
; https://www.sysnet.pe.kr/2/0/11720

.NET Framework: 798. C# - Hyper-V 가상 머신의 직렬 포트와 연결된 Named Pipe 간의 통신
; https://www.sysnet.pe.kr/2/0/11722

디버깅 기술: 169. Hyper-V의 VM에 대한 메모리 덤프를 뜨는 방법
; https://www.sysnet.pe.kr/2/0/12284

개발 환경 구성: 608. Hyper-V 가상 머신에 Console 모드로 로그인하는 방법
; https://www.sysnet.pe.kr/2/0/12859

개발 환경 구성: 664. Hyper-V에 설치한 리눅스 VM의 VHD 크기 늘리는 방법 - 두 번째 이야기
; https://www.sysnet.pe.kr/2/0/13246

Windows: 259. Hyper-V Generation 1 유형의 VM을 Generation 2 유형으로 바꾸는 방법
; https://www.sysnet.pe.kr/2/0/13564

개발 환경 구성: 718. Hyper-V - 리눅스 VM에 새로운 디스크 추가
; https://www.sysnet.pe.kr/2/0/13706

Windows: 280. Hyper-V의 3가지 Thread Scheduler (Classic, Core, Root)
; https://www.sysnet.pe.kr/2/0/13901




Hyper-V의 3가지 Thread Scheduler (Classic, Core, Root)

Windows 11 Hyper-V에 올린 VM의 경우, 속성 창의 "Processor" 정보를 보면 이런 경고가 나옵니다.

hyperv_cpu_is_zero_2.png

Hyper-V is not configured to enable processor resource controls.

Learn more about Hyper-V processor configuration options.

반면, Windows Server 2025의 Hyper-V에 올린 VM의 경우, 이런 경고가 나오지 않습니다. 이유는 간단한데요, Windows 11 Hyper-V의 경우엔 Root scheduler, Windows Server의 경우에는 Core Scheduler를 기본으로 채택하고 있기 때문입니다.

따라서, Windows 11의 경우에도 Core 또는 Classic Scheduler를 사용하도록 설정하면 해당 경고가 나오지 않는데, 딱히 권장하지는 않으므로 그냥 경고를 무시하면 됩니다. (이유는 아래에서 설명합니다.)

참고로, scheduler 유형은 bcdedit 명령을 통해서 설정할 수 있고,

// 관리자 권한 요구

C:\Windows\System32> bcdedit /set hypervisorschedulertype Core

* 주의: hypervisorschedulertype을 바꾸고 나서 재부팅하기 전에 현재 실행 중인 모든 VM을 (저장이 아닌) 중지해야 합니다.
* 그렇지 않으면 재부팅 후 VM이 로딩되지 않습니다.

저렇게 명시적으로 설정한 경우에는 마찬가지로 bcdedit 명령어를 통해 확인까지 가능합니다.

C:\Windows\System32> bcdedit

Windows Boot Manager
--------------------
identifier              {bootmgr}
...[생략]...

Windows Boot Loader
-------------------
identifier              {current}
...[생략]...
hypervisorlaunchtype    Auto
hypervisorschedulertype Core

하지만 명시적으로 설정하지 않은 경우에는 hypervisorschedulertype 항목이 출력되지 않으므로 알 수가 없는데요, 이럴 때는 이벤트 로그를 통해 확인할 수 있다고 합니다.

PS C:\temp> Get-WinEvent -FilterHashTable @{ProviderName="Microsoft-Windows-Hyper-V-Hypervisor"; ID=2} -MaxEvents 1
   ProviderName: Microsoft-Windows-Hyper-V-Hypervisor

TimeCreated                      Id LevelDisplayName Message
-----------                      -- ---------------- -------
2025-02-13 오전 9:55:36             2 Information      Hypervisor scheduler type is 0x4. 

위의 경우 0x4로 나오는데 이것은 "root scheduler"를 사용하는 경우로, 기타 나올 수 있는 숫자 유형은 다음과 같습니다.

1 = Classic scheduler, SMT disabled
2 = Classic scheduler
3 = Core scheduler
4 = Root scheduler




기왕에 이렇게 됐으니, 이참에 classic, core, root 방식의 차이점을 알고 넘어가는 것도 좋겠습니다. ^^ 검색해 보면, 아래의 글이 나오는데,

What is the Hyper-V Core Scheduler?
; https://www.altaro.com/hyper-v/hyper-v-core-scheduler/

간단하게 정리해 볼까요? ^^

우선 (그동안 기본적으로 사용했던) Classic은 Host/VM의 모든 스레드가 동등하게 CPU 자원을 나눠가지는 방식입니다. 그런데, 이 방식에는 한 가지 문제점이 있습니다.

바로, Hyper-Threading이 활성화된 Core의 경우 Cache를 공유하고 있어 서로 다른 VM의 스레드가 1개의 Core에서 동시에 실행될 때 Cache의 내용을 어느 한 쪽이 위/변조할 수 있다는 것입니다. (아마도, Spectre/Meltdown과 같은 Side-Channel 공격과 관련해 한창 이슈가 되었던 그 시절에 VM의 이런 문제도 떠오르지 않았나 싶습니다.)

그래서, 이에 대한 해법으로 내놓은 방식이 "Core Scheduler"입니다. cache 공유를 막자는 이유이므로, Core Scheduler는 VM의 스레드를 물리적인 Core마다 1개만 할당하는 방식입니다. 그러니까, 아래의 그림처럼 서로 다른 VM의 스레드가 코어를 공유하지 않게 된 것입니다.

// (X) Core Scheduler에서는 이렇게 서로 다른 VM이 1개의 Core를 공유하지 못함
┏────────────────────────────────────┓
│       Pyhsical Core (HT-enabled)   │
│  ┏─────────────┓  ┏─────────────┓  │
│  │ VM1         │  │ VM2         │  │
│  │ Thread 1    │  │ Thread 1    │  │
│  ┗─────────────┛  ┗─────────────┛  │
┗────────────────────────────────────┛

심지어, 같은 VM의 스레드도 Core를 공유하지 못합니다. 왜냐하면, VM은 호스트 측의 Core를 마치 Hyper-Threading이 비활성화된 것처럼 사용하기 때문에 아래와 같은 식으로 스레드가 배분되는 것입니다.

// Core Scheduler의 경우 개별 VM 스레드마다 1개의 Core로 스케줄링
┏────────────────────────────────────┓  ┏────────────────────────────────────┓
│       Pyhsical Core (HT-enabled)   │  │       Pyhsical Core (HT-enabled)   │
│  ┏─────────────┓  ┏─────────────┓  │  │  ┏─────────────┓  ┏─────────────┓  │
│  │ VM1         │  │             │  │  │  │ VM1         │  │             │  │
│  │ Thread 1    │  │             │  │  │  │ Thread 1    │  │             │  │
│  ┗─────────────┛  ┗─────────────┛  │  │  ┗─────────────┛  ┗─────────────┛  │
┗────────────────────────────────────┛  ┗────────────────────────────────────┛

이상하다고 여길 수 있지만, 달리 생각해 호스트 측의 BIOS 설정에서 Hyper-Threading을 비활성화하는 것과 같은 효과라고 보시면 됩니다. 즉, Classic Scheduler 방식만 있을 때는 굳이 VM에 HT를 활성화하지 않아도 Hyper-V가 평등하게 CPU 자원을 나눠주기 때문에 문제가 없었는데, 그것이 Core Scheduler로 바뀌면서 VM 측에 HT를 인지하도록 설정하는 것이 필요해진 것입니다.

어쨌든, 비효율적이죠? 실제로 이런 상황이 있어서 아래와 같은 질문이 나온 것입니다.

Windows Server 2019 HyperV strange CPU usage pattern
; https://learn.microsoft.com/en-us/answers/questions/133565/windows-server-2019-hyperv-strange-cpu-usage-patte

그리고 위의 질문에 있는 이미지가 이 상황을 잘 설명해 줍니다.

smt_enabled_1.png

이 문제를 해결하려면, 가상 머신이 HT를 인지하도록 설정해야 하는데 그래서 Hyper-V는 이와 관련해 별도로 HwThreadCountPerCore 옵션을 제공합니다.

Enable SMT in guest VMs
; https://learn.microsoft.com/en-us/windows-server/virtualization/hyper-v/manage/manage-hyper-v-scheduler-types#virtual-machine-cpu-resource-controls-and-the-root-scheduler

How to Enable Processor Resource Controls in Hyper-V
; https://huybien.com/how-to-enable-processor-resource-controls-in-hyper-v/

Set-VMProcessor -VMName <VMName> -HwThreadCountPerCore <n>, where <n>

// 0: Inherit SMT topology from the host
// 1: Non-SMT
// Values > 1: the desired number of SMT threads per core. May not exceed the number of physical SMT threads per core.

결국 (근래에는) 대개의 경우 아래와 같은 정도로 설정한다고 보면 됩니다.

// 대개의 경우, 호스트 측은 HT를 활성화시켰을 것이고, VM은 호스트의 설정을 따라가도록 설정
PS C:\Windows\System32> Set-VMProcessor -VMName win11en -HwThreadCountPerCore 0

// 대상 VM의 SMT 설정 확인
PS C:\Windows\System32> (Get-VMProcessor -VMName win11en).HwThreadCountPerCore
0

이렇게 되면 VM 측의 스레드가 2의 배수라면 같은 Core에서 실행될 수 있습니다.

// (O) HwThreadCountPerCore == 0 또는 2인 경우 같은 VM에 있는 스레드라면 같은 Core를 공유할 수 있음
┏────────────────────────────────────┓ ┏────────────────────────────────────┓
│       Pyhsical Core (HT-enabled)   │ │       Pyhsical Core (HT-enabled)   │
│  ┏─────────────┓  ┏─────────────┓  │ │  ┏─────────────┓  ┏─────────────┓  │
│  │ VM1         │  │ VM1         │  │ │  │ VM1         │  │             │  │
│  │ Thread 1    │  │ Thread 2    │  │ │  │ Thread 3    │  │             │  │
│  ┗─────────────┛  ┗─────────────┛  │ │  ┗─────────────┛  ┗─────────────┛  │
┗────────────────────────────────────┛ ┗────────────────────────────────────┛




마지막으로 (Windows 10 1803부터 지원하기 시작한) root scheudler는 위의 내용과 상관없이 이해할 수 있는데요, 이것은 스케줄링 권한을 루트 파티션에 맡겨 호스트 OS에 CPU 자원을 좀 더 할당하게 해줍니다.

이런 방식으로 인해, root scheduler는 서버 유형의 환경에서는 지원하지 않는다고 합니다.

// https://learn.microsoft.com/en-us/windows-server/virtualization/hyper-v/manage/manage-hyper-v-scheduler-types#select-the-hypervisor-scheduler-type-on-windows-server

The hypervisor root scheduler isn't supported on Windows Server Hyper-V at this time. Hyper-V administrators shouldn't attempt to configure the root scheduler for use with server virtualization scenarios.


그러고 보니, 제 테스트 머신 중에 "root scheduler"로 나온 것은 Windows 11이었고, Windows Server 2022/2025"는 모두 "core scheduler"였습니다.

현실적으로, 클라이언트용 PC라면 VM 서비스를 위한 것은 아니므로 root scheduler가 맞는 선택일 것입니다.




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]







[최초 등록일: ]
[최종 수정일: 3/9/2025]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 106  107  108  109  [110]  111  112  113  114  115  116  117  118  119  120  ...
NoWriterDateCnt.TitleFile(s)
11175정성태4/5/201725938.NET Framework: 652. C# 개발자를 위한 C++ COM 객체의 기본 구현 방식 설명파일 다운로드1
11174정성태4/3/201719483VC++: 116. Visual Studio 단위 테스트 - Failed to set up the execution context to run the test
11173정성태4/3/201723097VC++: 115. Visual Studio에서 C++ DLL을 대상으로 단위 테스트할 때 비정상 종료한다면?파일 다운로드1
11172정성태4/3/201722216.NET Framework: 651. C# - 특정 EXE 프로세스를 종료시킨 EXE를 찾아내는 방법파일 다운로드1
11171정성태3/31/201718950VS.NET IDE: 114. Visual Studio 디버깅 경고 창 - You are debugging a Release build of ...
11170정성태3/31/201720829.NET Framework: 650. C# - CachedAnonymousMethodDelegate 유형의 코드 생성
11169정성태3/30/201720719VC++: 114. C++ vtable의 가상 함수 호출 가로채기파일 다운로드1
11168정성태3/29/201724008VC++: 113. C++ 클래스 상속 관계의 vtable 생성 과정
11167정성태3/28/201724287VC++: 112. C++의 가상 함수 테이블 (vtable)은 언제 생성될까요? [2]
11166정성태3/28/201718505오류 유형: 382. System.Data.SqlClient.SqlException - Arithmetic overflow error converting IDENTITY to data type int.
11165정성태3/27/201721811오류 유형: 381. Visual C++에서 min, max 함수를 사용한 경우 C2589, C2059 컴파일 오류 발생
11164정성태3/27/201730159VC++: 111. C++ 클래스의 상속에 따른 메모리 구조 [2]파일 다운로드1
11163정성태3/25/201719989VC++: 110. CreateThread Win32 API에 C++ 클래스의 멤버 함수를 전달하는 방법파일 다운로드1
11162정성태3/24/201724191오류 유형: 380. Visual Studio 빌드 실패 - The OutputPath property is not set for project
11161정성태3/24/201716910오류 유형: 379. ICOMAdminCatalog.GetCollection 호출 시 0x80070422 예외 발생
11160정성태3/23/201721868.NET Framework: 649. ASP.NET - Server cannot append header after HTTP headers have been sent. (HTTP 헤더를 보낸 후에는 서버에서 헤더를 추가할 수 없습니다.)파일 다운로드1
11159정성태3/23/201719078Windows: 136. Memory-mapped File은 Private Bytes 크기에 포함될까요?파일 다운로드1
11158정성태3/22/201718655디버깅 기술: 85. Windbg - SOS 디버깅 사례 System.NullReferenceException 예외 추적
11157정성태3/22/201721910.NET Framework: 648. Dictionary<TKey, TValue>를 deep copy하는 방법파일 다운로드1
11156정성태3/21/201722600.NET Framework: 647. 닷넷(C#) 코드로 인증서 요청 코드 만드는 방법파일 다운로드1
11155정성태3/21/201722889.NET Framework: 646. SslStream의 CipherAlgorithm 선택이 가능할까요?파일 다운로드1
11154정성태3/5/201729796VC++: 109. DLL에서 STL 객체를 인자/반환값으로 갖는 함수를 제공할 때, 그 함수를 외부에서 사용하는 경우 비정상 종료한다면? [2]파일 다운로드1
11153정성태3/5/201729181VC++: 108. DLL에 정의된 C++ template 클래스의 복사 생성자 문제파일 다운로드1
11152정성태3/4/201722915VC++: 107. VirtualAlloc, HeapAlloc, GlobalAlloc, LocalAlloc, malloc, new의 차이점파일 다운로드1
11151정성태3/3/201723425VC++: 106. DLL 개발자가 주의해야 할 Secure CRT 함수 사용 [1]파일 다운로드1
11150정성태2/21/201719357.NET Framework: 645. Visual Studio Fakes 기능에서 Shim... 클래스가 생성되지 않는 경우 [5]
... 106  107  108  109  [110]  111  112  113  114  115  116  117  118  119  120  ...