Microsoft MVP성태의 닷넷 이야기
Windows: 280. Hyper-V의 3가지 Thread Scheduler (Classic, Core, Root) [링크 복사], [링크+제목 복사],
조회: 2106
글쓴 사람
정성태 (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

비밀번호

댓글 작성자
 




1  2  3  4  5  6  [7]  8  9  10  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
13768정성태10/15/20245362C/C++: 179. C++ - _O_WTEXT, _O_U16TEXT, _O_U8TEXT의 Unicode stream 모드파일 다운로드2
13767정성태10/14/20244755오류 유형: 929. bpftrace 수행 시 "ERROR: Could not resolve symbol: /proc/self/exe:BEGIN_trigger"
13766정성태10/14/20244537C/C++: 178. C++ - 파일에 대한 Text 모드의 "translated" 동작파일 다운로드1
13765정성태10/12/20245244오류 유형: 928. go build 시 "package maps is not in GOROOT" 오류
13764정성태10/11/20245611Linux: 85. Ubuntu - 원하는 golang 버전 설치
13763정성태10/11/20244970Linux: 84. WSL / Ubuntu 20.04 - bpftool 설치
13762정성태10/11/20244992Linux: 83. WSL / Ubuntu 22.04 - bpftool 설치
13761정성태10/11/20244900오류 유형: 927. WSL / Ubuntu - /usr/include/linux/types.h:5:10: fatal error: 'asm/types.h' file not found
13760정성태10/11/20245437Linux: 82. Ubuntu - clang 최신(stable) 버전 설치
13759정성태10/10/20246348C/C++: 177. C++ - 자유 함수(free function) 및 주소 지정 가능한 함수(addressable function) [6]
13758정성태10/8/20245560오류 유형: 926. dotnet tools를 sudo로 실행하는 경우 command not found
13757정성태10/8/20245497닷넷: 2306. Linux - dotnet tool의 설치 디렉터리가 PATH 환경변수에 자동 등록이 되는 이유
13756정성태10/8/20245606오류 유형: 925. ssh로 docker 접근을 할 때 "... malformed HTTP status code ..." 오류 발생
13755정성태10/7/20245991닷넷: 2305. C# 13 - (9) 메서드 바인딩의 우선순위를 지정하는 OverloadResolutionPriority 특성 도입 (Overload resolution priority)파일 다운로드1
13754정성태10/4/20245559닷넷: 2304. C# 13 - (8) 부분 메서드 정의를 속성 및 인덱서에도 확대파일 다운로드1
13753정성태10/4/20245575Linux: 81. Linux - PATH 환경변수의 적용 규칙
13752정성태10/2/20246255닷넷: 2303. C# 13 - (7) ref struct의 interface 상속 및 제네릭 제약으로 사용 가능 [6]파일 다운로드1
13751정성태10/2/20245385C/C++: 176. C/C++ - ARM64로 포팅할 때 유의할 점
13750정성태10/1/20245277C/C++: 175. C++ - WinMain/wWinMain 호출 전의 CRT 초기화 단계
13749정성태9/30/20245517닷넷: 2302. C# - ssh-keygen으로 생성한 Private Key와 Public Key 연동파일 다운로드1
13748정성태9/29/20245729닷넷: 2301. C# - BigInteger 타입이 byte 배열로 직렬화하는 방식
13747정성태9/28/20245564닷넷: 2300. C# - OpenSSH의 공개키 파일에 대한 "BEGIN OPENSSH PUBLIC KEY" / "END OPENSSH PUBLIC KEY" PEM 포맷파일 다운로드1
13746정성태9/28/20245670오류 유형: 924. Python - LocalProtocolError("Illegal header value ...")
13745정성태9/28/20245533Linux: 80. 리눅스 - 실행 중인 프로세스 내부의 환경변수 설정을 구하는 방법 (lldb)
13744정성태9/27/20245957닷넷: 2299. C# - Windows Hello 사용자 인증 다이얼로그 표시하기파일 다운로드1
13743정성태9/26/20246401닷넷: 2298. C# - Console 프로젝트에서의 await 대상으로 Main 스레드 활용하는 방법 [1]
1  2  3  4  5  6  [7]  8  9  10  11  12  13  14  15  ...