win32 / 프로세서 캐시 파라미터 읽어오기

1. Set-Associative 캐시

현대의 대부분의 프로세서는 아래 그림과 같은 Set-Associative 캐시 구조를 가집니다. 또 하나만 가지는게 아니라 L1, L2, L3처럼 크기와 레이턴시가 다르게 계층별로 구분되어 있습니다. 이 글에서 이러한 캐시구조를 가지는 프로세서의 각 캐시 파라미터들을 Windows 운영체제에서 읽어오는 방법을 소개하겠습니다.

<출처: https://en.wikipedia.org/wiki/Cache_placement_policies>

2. 캐시 파라미터

그 전에 캐시의 대략적인 성능은 m C S E B t s b의 8가지 파라미터로 표현할 수 있습니다. 여기서 각각의 의미는 아래와 같습니다.

  • m: 사용되는 아키텍처의 주소 비트의 크기, 대부분 64또는 32.
  • C: 전체 캐시의 바이트 단위 크기, C=S * E * B
  • B: 블록 하나의 바이트 단위 크기
  • E: 캐시의 Set 하나당 블록의 개수.
  • S: 캐시의 Set의 개수.
  • t: 태그 비트의 크기, t = m – s – b
  • s: set 비트의 크기, S=2^s
  • b: block offset 비트의 크기, B=2^s

예를 들면 위의 그림에서 나온 캐시는 캐시 파라미터로 아래처럼 표현할 수 있습니다. 그림의 오른쪽 위에 나와있다시피 메모리 크기가 16KiB = 16384B = 2^14이기 때문에 m=14가 됩니다.

mCBEStsb
14bits512Byte4B2-ways32sets7bits5bits2bits

3. 코드

이제 본격적으로 코드를 알아봅시다. <Windows.h>GetLogicalProcessorInformation() API가 존재합니다. 프로세서와 관련된 몇몇 정보를 가져올 수 있는데 그 중 캐시정보도 포함됩니다. 첫번째 호출에서 전체 크기를 읽어오고, 두번째 호출에서 SYSTEM_LOGICAL_PROCESSOR_INFORMATION구조체의 배열로 표현되는 실제 데이터를 가져옵니다. 캐시와 상관없는 데이터도 다수 포함되기 때문에 RelationCache에 해당하는 경우만 살핍니다.

main.cpp
#define WIN32_LEAN_AND_MEAN
#include <iostream>
#include <vector>
#include <Windows.h>

using namespace std;

int main() {
	DWORD buffer_size = 0;
	GetLogicalProcessorInformation(nullptr, &buffer_size);

	vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> infos(buffer_size);
	GetLogicalProcessorInformation(&infos[0], &buffer_size);

	for (const auto& info : infos) {
		if (info.Relationship != RelationCache) continue;

		const auto& cache = info.Cache;

		cout << 'L' << (int)cache.Level;
		if (cache.Type == CacheData)
			cout << " d-cache\n";
		else if (cache.Type == CacheInstruction)
			cout << " i-cache\n";
		else if (cache.Type == CacheUnified)
			cout << " unified-cache\n";

		cout << "size: " << cache.Size << "bytes\n";
		cout << "   S: " << cache.Size / cache.Associativity / cache.LineSize << "sets\n";
		cout << "   E: " << (int)cache.Associativity << "-ways\n";
		cout << "   B: " << (int)cache.LineSize << "bytes\n\n";
	}

	return 0;
}
C++

4. 결과

현재 사용중인 CPU가 i7 11800H인데 전체 출력결과는 아래와 같습니다. L1 캐시는 데이터 캐시와 인스트럭션 캐시가 따로 나뉘어 있고, L2 캐시와 함께 코어마다 존재합니다. 반면 L3캐시는 용량이 큰(24MiB) 대신에 프로세서에 하나 존재합니다.

output
L1 d-cache
size: 49152bytes
   S: 64sets
   E: 12-ways
   B: 64bytes

L1 i-cache
size: 32768bytes
   S: 64sets
   E: 8-ways
   B: 64bytes

L2 unified-cache
size: 1310720bytes
   S: 1024sets
   E: 20-ways
   B: 64bytes

L1 d-cache
size: 49152bytes
   S: 64sets
   E: 12-ways
   B: 64bytes

L1 i-cache
size: 32768bytes
   S: 64sets
   E: 8-ways
   B: 64bytes

L2 unified-cache
size: 1310720bytes
   S: 1024sets
   E: 20-ways
   B: 64bytes

L1 d-cache
size: 49152bytes
   S: 64sets
   E: 12-ways
   B: 64bytes

L1 i-cache
size: 32768bytes
   S: 64sets
   E: 8-ways
   B: 64bytes

L2 unified-cache
size: 1310720bytes
   S: 1024sets
   E: 20-ways
   B: 64bytes

L1 d-cache
size: 49152bytes
   S: 64sets
   E: 12-ways
   B: 64bytes

L1 i-cache
size: 32768bytes
   S: 64sets
   E: 8-ways
   B: 64bytes

L2 unified-cache
size: 1310720bytes
   S: 1024sets
   E: 20-ways
   B: 64bytes

L1 d-cache
size: 49152bytes
   S: 64sets
   E: 12-ways
   B: 64bytes

L1 i-cache
size: 32768bytes
   S: 64sets
   E: 8-ways
   B: 64bytes

L2 unified-cache
size: 1310720bytes
   S: 1024sets
   E: 20-ways
   B: 64bytes

L1 d-cache
size: 49152bytes
   S: 64sets
   E: 12-ways
   B: 64bytes

L1 i-cache
size: 32768bytes
   S: 64sets
   E: 8-ways
   B: 64bytes

L2 unified-cache
size: 1310720bytes
   S: 1024sets
   E: 20-ways
   B: 64bytes

L1 d-cache
size: 49152bytes
   S: 64sets
   E: 12-ways
   B: 64bytes

L1 i-cache
size: 32768bytes
   S: 64sets
   E: 8-ways
   B: 64bytes

L2 unified-cache
size: 1310720bytes
   S: 1024sets
   E: 20-ways
   B: 64bytes

L1 d-cache
size: 49152bytes
   S: 64sets
   E: 12-ways
   B: 64bytes

L1 i-cache
size: 32768bytes
   S: 64sets
   E: 8-ways
   B: 64bytes

L2 unified-cache
size: 1310720bytes
   S: 1024sets
   E: 20-ways
   B: 64bytes

L3 unified-cache
size: 25165824bytes
   S: 32768sets
   E: 12-ways
   B: 64bytes

L1, L2 캐시는 여러개 존재하지만 파라미터는 모두 같습니다. 위에서 설명한 캐시 파라미터로 이를 표현해봅시다. 참고로 KiB와 MiB는 각각 2^10, 2^20 단위이고 각각 키비바이트, 메비바이트라고 읽습니다.

개수mCBEStsb
L1-d864b48KiB64B12-ways64sets52b6b6b
L1-i864b32KiB64B8-ways64sets52b6b6b
L2864b1.25MiB64B20-ways1024sets48b10b6b
L3164b24MiB64B12-ways32768sets43b15b6b

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다