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

비밀번호

댓글 작성자
 




... 46  47  48  49  50  51  52  53  54  [55]  56  57  58  59  60  ...
NoWriterDateCnt.TitleFile(s)
12560정성태3/11/202117688개발 환경 구성: 549. ssh-keygen으로 생성한 PKCS#1 개인키/공개키 파일을 각각 PKCS8/PEM 형식으로 변환하는 방법
12559정성태3/11/202117949.NET Framework: 1028. 닷넷 5 환경의 Web API에 OpenAPI 적용을 위한 NSwag 또는 Swashbuckle 패키지 사용 [2]파일 다운로드1
12558정성태3/10/202117009Windows: 192. Power Automate Desktop (Preview) 소개 - Bitvise SSH Client 제어 [1]
12557정성태3/10/202115248Windows: 191. 탐색기의 보안 탭에 있는 "Object name" 경로에 LEFT-TO-RIGHT EMBEDDING 제어 문자가 포함되는 문제
12556정성태3/9/202113523오류 유형: 703. PowerShell ISE의 Debug / Toggle Breakpoint 메뉴가 비활성 상태인 경우
12555정성태3/8/202116834Windows: 190. C# - 레지스트리에 등록된 DigitalProductId로부터 라이선스 키(Product Key)를 알아내는 방법파일 다운로드2
12554정성태3/8/202116368.NET Framework: 1027. 닷넷 응용 프로그램을 위한 PDB 옵션 - full, pdbonly, portable, embedded
12553정성태3/5/202116389개발 환경 구성: 548. 기존 .NET Framework 프로젝트를 .NET Core/5+ 용으로 변환해 주는 upgrade-assistant, try-convert 도구 소개 [4]
12552정성태3/5/202115846개발 환경 구성: 547. github workflow/actions에서 Visual Studio Marketplace 패키지 등록하는 방법
12551정성태3/5/202114195오류 유형: 702. 비주얼 스튜디오 - The 'CascadePackage' package did not load correctly. (2)
12550정성태3/5/202113944오류 유형: 701. Live Share 1.0.3713.0 버전을 1.0.3884.0으로 업데이트 이후 ContactServiceModelPackage 오류 발생하는 문제
12549정성태3/4/202115216오류 유형: 700. VsixPublisher를 이용한 등록 시 다양한 오류 유형 해결책
12548정성태3/4/202116349개발 환경 구성: 546. github workflow/actions에서 nuget 패키지 등록하는 방법
12547정성태3/3/202117008오류 유형: 699. 비주얼 스튜디오 - The 'CascadePackage' package did not load correctly.
12546정성태3/3/202116853개발 환경 구성: 545. github workflow/actions에서 빌드시 snk 파일 다루는 방법 - Encrypted secrets
12545정성태3/2/202119722.NET Framework: 1026. 닷넷 5에 추가된 POH (Pinned Object Heap) [10]
12544정성태2/26/202119927.NET Framework: 1025. C# - Control의 Invalidate, Update, Refresh 차이점 [2]
12543정성태2/26/202117902VS.NET IDE: 158. C# - 디자인 타임(design-time)과 런타임(runtime)의 코드 실행 구분
12542정성태2/20/202119567개발 환경 구성: 544. github repo의 Release 활성화 및 Actions를 이용한 자동화 방법 [1]
12541정성태2/18/202117141개발 환경 구성: 543. 애저듣보잡 - Github Workflow/Actions 소개
12540정성태2/17/202118246.NET Framework: 1024. C# - Win32 API에 대한 P/Invoke를 대신하는 Microsoft.Windows.CsWin32 패키지
12539정성태2/16/202118153Windows: 189. WM_TIMER의 동작 방식 개요파일 다운로드1
12538정성태2/15/202118643.NET Framework: 1023. C# - GC 힙이 아닌 Native 힙에 인스턴스 생성 - 0SuperComicLib.LowLevel 라이브러리 소개 [2]
12537정성태2/11/202119323.NET Framework: 1022. UI 요소의 접근은 반드시 그 UI를 만든 스레드에서! - 두 번째 이야기 [2]
12536정성태2/9/202118186개발 환경 구성: 542. BDP(Bandwidth-delay product)와 TCP Receive Window
12535정성태2/9/202117268개발 환경 구성: 541. Wireshark로 확인하는 LSO(Large Send Offload), RSC(Receive Segment Coalescing) 옵션
... 46  47  48  49  50  51  52  53  54  [55]  56  57  58  59  60  ...