메인 콘텐츠로 건너뛰기
CPU 제조업체는 성능, 전력 사용량, 다이 면적 사이에서 끊임없이 균형을 맞추고 있습니다. 그 이유는 고객마다 사용 패턴과 우선 순위가 다르기 때문입니다. 데스크톱 컴퓨터를 사용하는 사람은 성능에 더 관심이 있는 반면, 노트북 사용자는 배터리 수명에 더 관심이 있습니다. 다이 면적이 작을수록 생산 비용이 저렴해질 수 있습니다. 이처럼 상충하는 요구 사항을 해결하기 위해 CPU 제조업체는 비용 효율성을 유지하면서 시스템이 현재 워크로드 요구에 동적으로 적응할 수 있도록 하는 _이기종 아키텍처_를 설계합니다. CPU 제조업체는 효율성 수준이 서로 다른 CPU 코어를 사용하여 이기종 토폴로지를 구현했습니다. 이 방식은 기존 CPU 아키텍처의 일부 코어를 전력 효율이 더 높은 코어로 대체했습니다. 사용자가 CPU의 최대 성능을 필요로 하지 않는 경우 OS는 성능이 더 높은 코어를 꺼서 상당한 양의 전력을 절약하므로 배터리 수명이 길어집니다. 더 많은 성능이 필요한 경우 OS는 증가한 워크로드를 처리하기 위해 성능이 더 높은 코어를 동적으로 켤 수 있습니다.

하드웨어

다양한 독립 하드웨어 공급업체(IHV)는 이기종 CPU 토폴로지를 서로 다르게 정의합니다. Intel과 Qualcomm은 Performance와 Efficiency라는 용어를 사용하고, AMD는 Performance와 Compact라는 용어를 사용합니다. 각 공급업체는 코어 토폴로지를 설계할 때 성능과 효율성 사이에서 절충합니다. 다음 예는 관련된 설계 선택 사항의 일부를 보여 줍니다.
  • 서로 다른 캐시 크기
    • 코어마다 캐시 크기가 다를 수 있습니다.
    • 예를 들어 성능 코어는 더 큰 L1 및 L2 캐시를 가질 수 있습니다.
  • 캐시 공유
    • 코어 간 캐시 공유 수준이 다양할 수 있습니다.
    • 예를 들어 고성능 코어는 각각 전용 L2 캐시를 가지는 반면, 효율이 더 높은 코어는 단일 L2 캐시를 공유할 수 있습니다.
  • SMT(동시 멀티스레딩) 지원
    • 일부 코어는 SMT를 지원하지만 다른 코어는 지원하지 않을 수 있습니다.
    • Intel은 SMT를 _Hyper-Threading_이라고 부릅니다.
  • 내부 코어 레이아웃
    • 코어 유형에 따라 내부 리소스가 다를 수 있습니다.
    • 예를 들어 성능 코어에는 더 많은 부동 소수점 파이프, ALU 파이프 또는 더 넓은 데이터 레인이 포함될 수 있습니다.
  • 최대 주파수
    • 코어 유형 간 최대 주파수가 다를 수 있습니다.
    • 예를 들어 성능 코어는 효율 코어보다 더 높은 주파수에 도달할 수 있습니다.
이러한 변경 사항은 CPU 내 코어 전반에서 성능과 전력 소비의 균형을 맞추도록 설계되었습니다. 주파수가 더 높은 코어는 전력 사용량이 증가하는 대신 성능이 더 높습니다. 여러 코어가 모두 같은 캐시를 공유하면 다이 크기가 줄어들어 전력 사용량이 감소하지만, 대신 성능이 저하됩니다. 목표는 성능과 전력 사용량에 대해 보다 동적인 선택을 허용하는 것입니다. 사용자가 최대 성능을 필요로 하지 않으면 OS는 전력 소비를 줄이기 위해 효율이 더 높은 코어로 전환합니다. Windows에는 CPU의 모든 코어가 동일한 ISA(명령 집합 아키텍처)를 지원해야 한다는 요구 사항이 있다는 점에 유의해야 합니다. 이 요구 사항은 CPU가 특정 명령 집합을 지원하는 경우 CPU의 모든 코어가 해당 집합을 지원한다는 것을 의미합니다. 예를 들어 CPU가 AVX2를 지원한다고 하면 모든 코어가 AVX2를 지원합니다. 성능 코어와 효율 코어의 차이에 대한 구체적인 내용은 각 IHV의 공식 문서를 참조하세요.

성능 수치

효율성 수준이 서로 다른 코어는 성능도 다를 것으로 예상됩니다. 한 코어는 성능을 위해 설계되었고 다른 코어는 전력 절약을 위해 설계되었습니다. 문제는 코어 간에 얼마나 차이가 나는가입니다. 표시된 데이터는 여러 IHV의 데이터를 종합한 것입니다. 각 IHV는 토폴로지에 대해 내린 선택에 따라 테스트별로 확장 정도가 다릅니다. 정확한 수치는 다르지만 패턴은 모든 IHV에서 비슷합니다. 또한 CPU 세대마다 서로 다른 절충을 하므로 상대적인 수치가 달라집니다. 기존의 모든 IHV와 세대에 걸친 수치를 산출하는 것은 이 문서의 범위를 벗어납니다.

합성 테스트

벡터 수학은 게임 타이틀이 한 프레임 내에서 수행하는 작업의 주요 부분입니다. 이 워크로드는 물리, AI, 렌더링 등 무엇이든 될 수 있습니다. 게임은 단일 128비트 SSE 레지스터에 들어가는 3개 또는 4개의 float로 구성된 벡터 유형을 사용하여 이 작업을 수행합니다. 이러한 작업은 내적, 행렬 곱셈, 제곱근 계산, 벡터 변환 등 광범위한 연산에 걸쳐 있습니다. 이러한 연산의 성능 차이는 전체 프레임 시간에 상당한 영향을 줄 수 있습니다. 다음 그래프는 일반적인 7가지 수학 연산을 수행하는 상대적 비용을 보여 줍니다. 측정에는 단일 128비트 SSE 레지스터에 저장된 4개의 32비트 부동 소수점 값으로 구성된 벡터를 사용합니다. 행렬은 4개의 벡터로 구성되며, 4개의 128비트 SSE 레지스터에 걸쳐 총 16개의 32비트 부동 소수점 값을 가집니다. 이러한 연산은 한 프레임 내에서 흔히 사용되므로 선택되었습니다.
  • 내적: 벡터의 내적을 계산합니다.
  • 벡터 변환: 벡터에 행렬을 곱하여 벡터를 변환합니다.
  • 벡터 덧셈: 두 벡터를 더합니다.
  • 외적: 두 벡터의 외적을 계산합니다.
  • 벡터 사인: 벡터의 각 요소에 대한 사인의 근삿값을 계산합니다.
  • 벡터 FMA(융합 곱셈-덧셈): 두 벡터를 곱하고 세 번째 벡터를 더합니다.
  • 역제곱근: 벡터 길이의 역제곱근을 계산합니다.
그림 1: 연산 수행에 걸린 시간. 낮을수록 좋습니다. 이기종 합성 벤치마크 수치 이 그래프에서 y축은 연산을 수행하는 데 걸린 시간입니다. 각 막대는 모든 IHV에서 측정한 연산 시간의 범위를 나타냅니다. 즉, 성능 코어 또는 효율 코어에서 테스트를 실행할 때의 최소 및 최대 시간입니다. 예상대로 코어 유형 간 성능은 다릅니다. 그러나 이 수치에서 얻을 수 있는 핵심 사항은 성능이 모든 연산과 IHV에서 동일한 비율로 확장되지 않는다는 것입니다. IHV 간 결과의 변동성은 대체로 비슷했지만, 일부는 변동성이 더 높았습니다. 변동성이 더 높은 연산은 주로 벡터 사인 및 역제곱근 연산에서 나타났습니다. 이 차이는 성능 코어와 효율 코어 간의 코어 아키텍처 선택에서 비롯됩니다. 이 차이의 정확한 원인은 여러 가지일 수 있습니다. 예를 들어 성능이 더 높은 코어에 부동 소수점 파이프가 더 많아 더 많은 연산을 병렬로 수행할 수 있습니다. 정확한 이유는 각 IHV와 CPU 세대마다 고유합니다. 특정 연산에 대해 성능 차이가 존재하지 않는 구성도 있을 수 있습니다. 결국 타이틀은 IHV 간의 이러한 변동성을 고려해야 합니다.

실제 환경

앞의 수치는 특정 벤치마크를 개별적으로 보여 주며, 전체 이야기의 일부만 알려 줍니다. 다음 수치는 두 개의 주 스레드(Simulation 및 Render)와 일련의 작업 스레드를 사용하는 AAA 게임 엔진의 벤치마크에서 나온 것입니다. 벤치마크는 세 가지 테스트 구성을 사용합니다.
  • 두 주 스레드가 고성능 코어에서만 실행됩니다.
  • 두 주 스레드가 효율 코어에서만 실행됩니다.
  • 두 주 스레드가 시스템의 모든 코어에서 실행됩니다.
각 테스트 구성에서 작업 스레드는 시스템의 모든 코어에서 자유롭게 이동할 수 있습니다. 렌더링 작업은 가능한 가장 낮은 해상도와 품질을 사용합니다. 이 설정은 전체 테스트 실행 동안 타이틀이 CPU 바운드 상태가 되도록 보장합니다. 또한 이 설정으로 인해 Simulation 스레드가 프레임 속도를 결정하는 원동력이 됩니다. 이 그래프는 한 프레임 동안 각 스레드에서 소비된 시간을 보여 줍니다. 평균 프레임 시간과 1% 상위 값을 모두 보여 줍니다. 1% 상위 값은 가장 긴 1% 프레임의 임계값입니다. 전체 프레임 중 1%만 이 값을 초과합니다. 이 수치는 끊김이 발생하는 프레임의 수를 잘 파악할 수 있게 해 줍니다. 평균에서 멀어질수록 타이틀의 끊김이 심합니다. 모든 경우에 값이 낮을수록 긴 프레임이 적고 눈에 보이는 끊김이 적다는 것을 의미합니다. 앞에서 언급했듯이 표시된 데이터는 여러 IHV의 데이터를 종합한 것입니다. 각 IHV는 토폴로지에 대해 내린 선택에 따라 테스트별로 확장 정도가 다릅니다. 정확한 수치는 다르지만 패턴은 IHV 전반에서 비슷합니다. CPU 세대마다 서로 다른 절충을 할 수 있으므로 상대적인 수치가 달라집니다. 기존의 모든 CPU IHV와 세대에 걸친 수치를 산출하는 것은 이 문서의 범위를 벗어납니다. 그림 2: 평균 소요 시간 및 1% 상위 값. 낮을수록 좋습니다. 이기종 실제 환경 벤치마크 수치 이 그래프에서 y축은 한 프레임에 걸린 시간입니다. 각 막대는 모든 IHV에서 측정한 연산 시간의 범위를 나타냅니다. 즉, 테스트한 각 스레드 토폴로지의 최소 및 최대 시간입니다. OS 스레드 스케줄러는 추론을 사용하여 스레드가 수행하는 작업량을 결정합니다. 이러한 추론은 OS의 선택과 IHV의 드라이버 조정이 결합된 것입니다. 스케줄러는 이 정보를 사용하여 특정 스레드가 어느 코어에서 실행되어야 하는지 선택합니다. 스레드가 많은 양의 작업을 수행하고 있다고 판단하면 스케줄러는 해당 스레드를 성능이 더 높은 코어로 이동합니다. 스케줄러 추론으로 인해 중요 스레드가 자유롭게 이동하도록 허용할 때 타이틀이 더 빠르게 실행되는 직관에 반하는 동작이 발생할 수 있습니다. 이 동작이 항상 발생하는 것은 아니며 워크로드, 코어 토폴로지 및 정확한 스케줄러 추론에 따라 달라집니다. 여기서 테스트한 경우에는 Simulation 스레드가 Render 스레드보다 각 프레임을 실행하는 데 더 많은 시간을 소비합니다. 스케줄러는 이 스레드를 성능이 더 높은 코어에 배치하는 것을 선호합니다. 또한 Render 스레드는 작업을 기다리며 일시 중단된 상태로 보내는 시간이 더 많으므로 성능이 더 낮은 코어에 배치하기로 결정합니다. 최종적으로 이 결정은 작업 스레드 중 하나가 사용할 수 있도록 성능이 더 높은 코어를 비워 줍니다. Render 스레드가 더 많은 작업을 수행하고 있었다면 이러한 상황은 발생하지 않았을 수 있습니다. 그러나 이 그래프에서 가장 흥미로운 점은 1% 상위 수치입니다. 중요 스레드가 자유롭게 이동할 때 평균이 같더라도, 1% 상위 값은 중요 스레드가 성능 코어에 고정되어 있을 때보다 나쁩니다. 이 상태는 중요 스레드가 자유롭게 이동할 때 프레임 속도의 끊김이 더 많다는 것을 의미합니다. 가장 일반적인 이유는 스케줄러 추론이 슬라이딩 윈도우를 기반으로 작동하기 때문입니다. 프레임에 필요한 작업이 급증할 때 이에 대응하는 데 시간이 걸립니다. 그 시간 동안 중요 스레드가 성능이 더 낮은 코어에서 실행될 수 있습니다.
각 제조업체는 하드웨어에 맞게 이러한 스케줄러 추론을 조정할 수 있습니다. 예를 들어 AMD에는 Workload Profile Scheduling이 있고 Intel에는 Thread Director 기술이 있습니다. 또한 각 IHV는 SoC의 특정 토폴로지에 맞게 추론을 조정하는 경향이 있습니다.

권장 사항

스레드 선호도

단일 효율성 클래스만 있는 데스크톱 컴퓨터에서 실행할 때의 스레드 선호도에 대한 권장 사항은 고정 스레드 선호도를 설정하지 말고 대신 스레드가 모든 코어에서 자유롭게 이동하도록 하는 것입니다. 이처럼 불확실한 주된 이유는 사용자의 컴퓨터에서 어떤 다른 프로세스가 실행될지 미리 알 수 없기 때문입니다. 고정 선호도가 있는 스레드가 시스템의 다른 높은 우선 순위 스레드와 코어를 공유하게 될 수 있습니다. 그 결과 타이틀 스레드는 실행 기회를 얻지 못하게 됩니다. 이러한 경합이 프레임에 중요한 스레드에서 발생하면 타이틀의 프레임 시간이 일정하지 않을 수 있습니다. OS가 타이틀 스레드를 계속 실행할 수 있도록 이동할 위치를 확보해야 합니다. 그러나 이기종 CPU에서 실행할 때는 이 권장 사항이 달라져야 합니다. 주된 이유는 OS가 타이틀의 스레드나 작업 중 어느 것이 프레임에 중요한지 반드시 알지는 못하기 때문입니다. OS에는 프레임에 중요한 스레드라고 판단하는 추론이 있지만, 이러한 추론은 여전히 잘못된 선택을 할 수 있습니다. OS가 이러한 스레드나 작업 중 하나를 성능이 더 낮은 코어로 이동하기로 결정하여 타이틀에서 성능 문제가 발생할 가능성이 높아질 수 있습니다. 권장 사항은 타이틀 스레드가 최소 3~4개의 코어에서 실행될 수 있도록 하는 것을 목표로 하며, 더 많을수록 좋습니다. 예를 들어 고성능 코어 1개와 저성능 코어 3개가 있는 저사양 시스템에서는 스레드가 모든 코어에서 자유롭게 이동하도록 허용해야 합니다. 성능 코어가 3개 이상인 컴퓨터에서는 프레임에 중요한 스레드를 해당 고성능 코어로만 제한할 수 있습니다. SMT도 지원하는 코어가 많은 고사양 컴퓨터에서는 일부 타이틀이 스레드를 물리적 코어에 고정하려고 할 수 있습니다. 이 기법은 여러 높은 우선 순위 스레드가 물리적 코어의 동일한 리소스를 공유할 때 물리적 코어 수준의 경합을 방지합니다. 하지만 일반적으로 이 경우는 고려하지 않는 것이 좋습니다. OS가 이미 시스템 전체에 이 동작을 적용하고 있습니다. OS는 먼저 물리적 코어에 스레드를 예약하고 필요한 경우에만 더 많은 논리적 코어를 사용합니다. 타이틀이 고려해야 하는 유일한 경우는 시스템에 타이틀의 중요 스레드를 지원할 만큼 충분한 고성능 코어가 있는 경우입니다. 이 경우 프레임에 중요한 스레드를 고성능 코어에 고정하는 것이 바람직할 수 있습니다. 그러나 이러한 스레드는 모든 고성능 코어에서 자유롭게 이동할 수 있어야 합니다. 경우에 따라 모든 스레드가 모든 코어에서 자유롭게 이동하도록 허용하면 성능이 향상될 수 있지만, 이 동작은 모든 CPU 제조업체에서 일관되지 않습니다. 타이틀이 모든 스레드에 걸쳐 워크로드의 균형을 완전히 맞출 수 있는 작업 가로채기 시스템을 구현하는 경우, 모든 작업 스레드는 모든 코어에서 자유롭게 이동할 수 있어야 합니다. 높은 우선 순위 작업 스레드인지 낮은 우선 순위 작업 스레드인지는 중요하지 않습니다. 작업 가로채기 알고리즘은 자동으로 부하의 균형을 맞추고 가장 짧은 시간에 가장 많은 작업을 완료할 수 있게 해 줍니다. 고성능 코어의 스레드는 프레임 동안 더 많은 작업을 실행합니다. 프레임에 중요한 스레드가 여러 개 있는 경우, 두 개의 프레임 중요 스레드가 동일한 코어에서 실행될 수 없도록 선호도를 설정하는 것이 유용할 수 있습니다. 예를 들어 프레임 중요 스레드가 두 개 있는 경우 서로 배타적 논리합(XOR)이 되도록 선호도를 설정하면 OS로 인해 스레드가 서로 경합할 가능성이 제거됩니다. 하지만 이 옵션은 각 프레임 중요 스레드가 최소 3~4개의 코어에서 자유롭게 이동할 수 있도록 하면서도 이 경우를 지원할 만큼 충분한 코어가 있는 경우에만 고려하세요.

스레드 토폴로지

이기종 환경에서 스레드에 작업을 할당하는 방법을 고려할 때 주요 데이터는 다양한 작업의 길이와 작업 간의 상호 작용 방식입니다. 각 작업의 평균 길이는 얼마인지, 작업 간의 종속성은 무엇인지, 각 작업의 우선 순위는 무엇인지 등입니다. 작업 스레드가 중요 스레드나 작업에서 발생하는 시간 급증을 얼마나 흡수할 수 있습니까? 이러한 스레드나 작업 중 하나가 35% 느리게 실행되면 프레임 시간에 얼마나 영향을 줍니까? 예를 들어 작업이 오래 실행되면 이 지연이 프레임의 나머지 부분에 얼마나 영향을 주는지, 해당 작업이 완료될 때까지 시스템이 중단되는지 등입니다. 중요 스레드나 작업에 추가 오버헤드를 더하여 이기종 시스템이 프레임 시간에 얼마나 영향을 주는지 확인하는 것이 유용할 수 있습니다. 테스트로, 작업이나 작업 블록이 임의로 25%~35%의 추가 시간이 걸리도록 만듭니다. 전체 프레임 시간의 변화 정도는 작업 시스템이 실행 급증을 얼마나 잘 흡수할 수 있는지를 나타냅니다. 이상적인 상황은 프레임 시간에 거의 변화가 없는 것입니다. 이는 시스템이 프레임 시간의 임의 급증을 흡수할 수 있다는 의미입니다. 급증은 성능이 더 낮은 코어에서 실행되거나 시스템의 다른 임의 프로세스가 CPU 시간을 사용하는 데서 비롯됩니다.

스레드 통신

잠금 기본 형식을 사용하는 스레드 통신에 대해서는 몇 가지 고려가 필요합니다. 컨텍스트 전환의 오버헤드는 새 스레드가 실행되기 전 수신 코어의 C-State와 밀접하게 연관되어 있습니다. 새 스레드가 실행을 시작하려면 코어가 실행 상태인 C0에 있어야 합니다. 비용이 가장 적은 경우는 코어가 이미 실행 중이어서 이미 C0에 있는 경우입니다. 그러나 코어가 유휴 상태이면 더 낮은 C-State에 있습니다. C-State의 수준은 더 깊은 절전 수준에 해당합니다. 더 깊은 절전 상태에서는 코어가 사용하는 전력이 줄어듭니다. 그러나 더 깊은 절전 상태에서 깨어나 다시 실행을 시작하는 데는 비용이 더 많이 듭니다. 가장 일반적인 저전력 C-state는 C1이며, 27μs의 오버헤드를 추가할 수 있습니다. 다음 C-state인 C2는 약 40100μs의 오버헤드를 추가할 수 있습니다. 정확한 수치는 IHV 및 SoC에 따라 다릅니다. 유휴 상태일 때 코어가 어떤 C-State에 있을지를 제어하는 변수는 많으며, 이는 응답성과 전력 사용량 사이의 균형입니다. 낮은 C-State는 높은 C-State보다 전력을 적게 사용합니다. 일반적으로 코어는 먼저 C1에 들어간 다음, 한동안 코드를 실행하지 않으면 C2로 전환합니다. 또 다른 우려 사항은 작업을 제출하는 스레드와 작업을 실행하는 스레드가 성능 프로필이 서로 다른 코어에 있을 때 어떤 일이 발생하는가입니다. 기술적으로 작업 스레드가 새 작업이 생성되는 것보다 더 빠르게 작업을 완료할 수 있습니다. 이 상황은 작업을 실행하는 스레드가 작업을 제출하는 스레드보다 더 빠른 코어에 있을 때 발생할 가능성이 더 높습니다. 작업을 실행하는 데 걸리는 시간이 작업을 생성하는 데 걸리는 시간보다 짧으면, 타이틀은 작업 스레드가 새 작업을 기다리며 계속 일시 중단되는 상황에 빠질 수 있습니다. 그 결과 작업 스레드가 계속 일시 중단되므로 작업 실행 비용이 더 커집니다. 컨텍스트 전환의 오버헤드 비용이 각 작업의 실행 시간에 추가됩니다. 이 오버헤드로 인해 역설적으로 성능이 더 높은 코어에서 실행할 때 프레임 속도가 더 낮아질 수 있습니다. 예를 들어 250μs가 걸리던 작업이 갑자기 275μs가 걸리기 시작할 수 있으며, 이 회귀는 10%의 성능 저하입니다. 이러한 경우 때문에 작업을 생성될 때마다 제출하는 대신 일괄 처리로 제출하는 것이 좋습니다. 예를 들어 시스템이 작업을 빌드하고, 작업을 제출하고, 작업을 빌드하고, 작업을 제출하는 등의 패턴을 따르는 경우입니다. 이 패턴은 대신 먼저 일괄로 빌드를 수행한 다음 모두 동시에 제출하도록 조정해야 합니다. 타이틀이 WaitForSingleObject가 필요한 개체를 사용하는 경우 작은 스핀 루프 안에 배치해야 합니다. 시간 제한을 0으로 하여 함수를 호출하고, 스핀이 끝나면 타이틀의 일반 시간 제한 값을 사용합니다. 하지만 이 문제에 대한 가장 좋은 해결책은 SRW(Slim Reader/Writer) 잠금, 임계 영역, WaitOnAddress와 같은 최신 동기화 API를 사용하는 것입니다. 이러한 동기화 API는 모두 내부적으로 어떤 형태의 스핀을 포함하므로 스레드가 계속 일시 중단되는 것을 방지할 수 있습니다. 이 스핀은 짧은 시간 동안 유지되는 잠금에 특히 유용합니다. 긴 스핀 잠금은 피하는 것이 중요합니다. 예를 들어 스레드가 수행할 작업을 기다리며 계속 스핀하는 패턴이 있습니다. 코어에서 수행해야 하는 다른 작업이 있으면 스케줄러는 결국 이 작업을 수행하기 위해 스핀 중인 스레드를 일시 중단합니다. 이러한 선점이 발생하면 일시 중단된 스레드가 상당한 시간 동안 일시 중단된 상태로 유지될 가능성이 높습니다. 이 동작은 모두 다른 스레드의 기아 상태를 방지하기 위해 수행됩니다. 타이틀은 일시 중단 시점을 거의 제어할 수 없으므로 프레임 속도의 끊김으로 이어질 수 있습니다.

작업 시스템

최상의 성능을 얻으려면 장기 실행되는 전용 프레임 중요 스레드에 의존하기보다는 작업을 중심으로 엔진을 구성하세요. 예를 들어 Simulation/Render 스레드 모델은 두 개의 영구적인 프레임 중요 스레드를 만듭니다. 그러나 긴 작업은 모든 작업 스레드가 프레임 중요 스레드처럼 동작하게 만들 수 있습니다. 작업에 10ms가 걸리면 해당 작업을 실행하는 스레드는 원래 역할과 관계없이 그 기간 동안 프레임에 중요한 스레드가 됩니다.

작업 가로채기

가장 중요한 권장 사항은 전체 작업 시스템에서 작업 가로채기를 사용하고 모든 프레임 중요 스레드가 작업 가로채기 알고리즘에 참여하도록 하는 것입니다. 예를 들어 렌더 스레드가 렌더링 관련 작업이 완료되기를 기다리고 있다면 해당 작업 중 일부를 실행해야 합니다. 이 동작은 이미 많은 게임 엔진에서 일반적인 관행입니다. 그러나 이러한 유형의 동작은 게임 엔진이 이기종 코어 및 가능한 OS 선점으로 인한 프레임 급증을 흡수하는 데 매우 중요하므로 여기서 언급할 가치가 있습니다. 작업 실행 시간이 길어지면 프레임 시간 급증의 위험이 커집니다. 이 동작은 작업이 성능이 더 낮은 코어에서 실행되거나 PC 내의 다른 작업으로 인해 발생할 수 있습니다. 권장 사항은 엔진이 작업 하나가 프레임의 약 2%를 차지하도록 목표로 하는 것입니다. 예를 들어 이 예산은 60fps로 실행되는 게임의 경우 약 333μs 이하를 의미합니다. 필요한 경우 2% 수치를 목표로 하기 위해 여러 개의 작은 작업을 하나의 큰 작업으로 일괄 처리해야 합니다. 이 방법은 작업 크기, 스레드 통신 및 급증 흡수 능력 간에 좋은 절충을 제공합니다. 다음 예는 긴 프레임 중요 작업이 시스템 성능에 미칠 수 있는 영향을 보여 줍니다. 이 예에서 각 작업은 동일한 수의 연산으로 구성됩니다. 이 예에서는 느린 코어에서 375μs, 빠른 코어에서 250μs가 걸리는 단일 작업이 있습니다. 가장 긴 작업(long pole)은 다른 작업보다 6배 더 비쌉니다. 최악의 상황은 가장 긴 작업이 느린 코어 중 하나에 배치되는 경우입니다. 이는 프레임 시간에 큰 영향을 줄 수 있습니다. 이 시나리오에서 작업을 실행하는 총 시간은 375μs의 6배인 2,250μs입니다. 그림 3: 느린 코어에서 실행되는 가장 긴 작업의 예. 느린 코어에서의 이기종 작업 가로채기 가장 긴 작업 예 가장 긴 작업이 더 빠른 코어에 배치되면 상황이 나아집니다. 이 경우 총 시간은 1,500μs입니다. 여전히 좋지는 않지만 더 낫습니다. 그림 4: 빠른 코어에서 실행되는 가장 긴 작업의 예. 빠른 코어에서의 이기종 작업 가로채기 가장 긴 작업 예 가장 좋은 결과는 작업 크기를 작고 균등하게 분산하여 가장 긴 작업을 피하는 것입니다. 이 예에서는 총 실행 시간이 1,125μs로 줄어들며, 이는 동일한 양의 작업을 완료하면서도 이전 예의 절반에 해당하는 시간입니다. 그림 5: 적절한 작업 길이를 사용하여 가장 긴 작업을 피합니다. 적절한 작업 길이를 사용한 이기종 작업 가로채기 더 중요한 것은 OS가 작업 실행 도중에 중단하려고 하면 시스템이 자동으로 워크로드의 균형을 맞춘다는 점입니다. 이 경우 OS는 빠른 코어에서 375μs 작업으로 타이틀을 중단했습니다. 이 재조정은 전체 프레임 시간에 영향을 주지 않으며, 프레임 시간은 1,125μs로 유지됩니다. 작업 중 하나가 느린 코어의 여유 시간으로 이동했습니다. 그림 6: 워크로드 재조정이 포함된 OS 중단 시에도 프레임 시간이 안정적으로 유지됩니다. 중단이 있는 경우 적절한 작업 길이를 사용한 이기종 작업 가로채기 이 예에서는 가장 긴 작업이 즉시 시작될 수 있는 경우만 다루며, 작업 큐에서 나중에야 시작될 수 있는 경우에는 상황이 더 나빠집니다. 이는 결국 암달의 법칙으로 귀결되며, 모든 시스템의 실행 시간은 해당 시스템에서 가장 오래 실행되는 부분에 의해 결정됩니다. 엔진은 이러한 가장 긴 스레드의 실행 시간을 늘리는 급증을 흡수할 수 없습니다. 이러한 급증은 더 느린 코어에서 실행되거나 시스템의 다른 높은 우선 순위 프로세스의 중단으로 인해 발생할 수 있습니다.

요약

이러한 권장 사항을 구현하면 다양한 CPU 아키텍처와 다른 Windows 프로세스의 간섭 속에서도 게임이 안정적으로 작동하고 복원력을 유지하도록 할 수 있습니다.

부록

코어의 효율성 클래스 확인

GetLogicalProcessorInformationEx 함수를 사용하여 시스템에 있는 각 프로세서의 효율성 클래스를 확인합니다. 함수가 반환한 데이터를 반복하면서 효율성 클래스와 코어 마스크가 포함된 RelationProcessorCore 블록을 찾습니다.

전력 사용량에 따른 스레드 고정

앞에서 언급했듯이 데스크톱 환경에서는 컴퓨터의 다른 프로세스로 인한 간섭 가능성 때문에 선호도를 사용한 코어 고정은 권장되지 않습니다. 그러나 Windows는 타이틀이 작업을 실행할 위치를 권장하는 힌트를 OS에 제공하는 방법을 제공합니다. 이러한 지침을 제공하는 한 가지 방법은 전원 관리 API를 사용하는 것입니다.

CPU 집합을 사용하여 효율성 클래스 쿼리

CPU 집합을 사용하는 것은 시스템에 있는 각 코어의 효율성 클래스를 쿼리하는 또 다른 방법입니다.

CPU 집합을 사용하여 스레드를 효율성 클래스에 할당

CPU 집합은 스레드의 선호도 마스크를 명시적으로 설정하는 대신 사용할 수도 있습니다. 명시적 선호도 마스크 대신 CPU 집합을 사용하는 것이 좋습니다.
마지막 수정일 2026년 10월 20일