주의 : 이 문서는 초심자 튜토리얼이 아닙니다. 기본 개념 정도는 안다고 가정합니다. 초심자는 [ Vulkan Tutorial ] 이나 [ Vulkan Samples Tutorial ] 을 보면서 같이 보시기 바랍니다.
주의 : 완전히 이해하고 작성한 글이 아니므로 잘못된 내용이 포함되어 있을 수 있습니다.
주의 : 이상하면 참고자료를 확인하세요.
정보 : 본문의 소스 코드는 Vulkan C++ exmaples and demos 를 기반으로 하고 있습니다.
Memory 관련해서 정리하다가 의문을 하나 가지게 되었습니다.
DEVICE_LOCAL 을 지정하면 디바이스 램에 메모리가 할당됩니다. 하지만 allocator 를 사용해서 메모리를 할당하면 어떻게 될까요?
먼저 간단하게 malloc 을 사용하는 allocator 용 콜백 함수들을 만들었습니다.
그리고 나서 allocator 에 할당합니다.
그리고 1000 개의 이미지를 생성해서 메모리를 할당해 줬습니다. 이 때 앞에서 만든 allocator 를 사용했습니다.
여러분은 어떤 결과가 나올 거라 예상하시나요? 저는 호스트 램의 메모리가 올라갈 것이라 예상했습니다. 왜냐하면 malloc 은 최종적으로 VirtualAlloc 과 연결되어 있고 호스트 램을 위한 메모리를 할당할 것이라 생각했기 때문이죠. 또한 호스트 메모리 중에서 공유 메모리를 사용할 것이라 생각했습니다.
하지만 결과는 충격적( ? )이었습니다. texture 프로세스는 1.6 GB 의 디바이스 메모리를 할당합니다. 제가 캡쳐하는 시점에 다른 응용프로그램이 디바이스 메모리를 사용했는지 수치가 좀 높네요. 실제 수치는 크게 신경쓰지 않으셔도 됩니다. 어디에서 메모리가 늘어나고 있는지가 중요하죠.
리소스 모니터를 보면 좀 다른 결과이긴 하더군요.
이러한 결과를 볼 때 다음과 같은 가설을 세울 수 있습니다.
- malloc 은 호출되는 문맥에 따라서 호스트 램에 메모리를 할당하기도 하고 디바이스 램에 메모리를 할당하기도 합니다. CUDA 버전 malloc 함수가 따로 있는 이유가 여기에 기반하는 것 같네요.
- "커밋 크기"는 램의 종류에 상관없이 프로세스가 사용한 메모리의 총량을 보여줍니다.
이건 제가 의도한 환경이 아닙니다. 그래서 이미 할당된 메모리를 반환하는 allocator 를 만들어 보기로 했습니다. Reallocation 과 Free 는 별 의미가 없으므로 대충 넘겼습니다. 메모리가 어디에 할당되는지 확인하는 용도로 만든 것이므로 그냥 Allocation 만 구현했습니다.
그래서 처음에 2 GB 를 할당하고 요청이 올 때마다 메모리를 증가시켜 그 주소를 반환할 겁니다.
실행해 보니 역시나 충격적인 결과를 줍니다. CPU 와 GPU 의 메모리 usage 는 동일한데, 리소스 모니터의 "커밋" 만 다른 결과를 줍니다.
제가 할당한 2 GB 만 고스란히 늘어났습니다. 즉 DEVICE_LOCAL 을 지정한 메모리를 할당할 때 호스트 메모리를 반환하면, 그것이 무시되고 자체적으로 메모리를 할당한다고 추측해 볼 수 있습니다. Allocator 를 사용하는 의미가 없는거죠.
정리
DEVICE_LOCAL 을 위한 메모리에 대해서 이미 할당된 메모리를 관리하는 allocator 를 사용하면 메모리가 늘어납니다. 그러므로 HOST_VISIBLE 이나 HOST 전용 메모리( 아무 속성도 지정되지 않은 것 )에 대해서만 allocator 를 사용하시기 바랍니다.
이런 관리를 하는 건 매우 귀찮은 일이기 때문에, allocator 를 사용하고 싶으시다면 GPU Open 에서 제공하는 "Vulkan Memory Allocator" 를 사용하는 것을 추천합니다. 헤더 파일 하나만 include 해서 사용할 수 있는 편리한 라이브러리입니다.
'Vulkan & OpenGL' 카테고리의 다른 글
[ Vulkan 연구 ] 번역 : Performance Tweets series: Barriers, fences, synchronization (0) | 2019.01.09 |
---|---|
[ Vulkan 연구 ] 번역 : Vulkan barriers explained (3) | 2019.01.08 |
[ Vulkan 연구 ] Synchronization Mechanisms (1) | 2019.01.06 |
[ Vulkan 연구 ] External Synchronization (0) | 2019.01.05 |
[ Vulkan 연구 ] Vulkan Api Version (0) | 2018.12.25 |
[ Vulkan 연구 ] Memory heaps & types (0) | 2018.12.03 |
[ Vulkan 연구 ] Optimal Tiling (2) | 2018.11.20 |
[ Vulkan 연구 ] Memory Usage (0) | 2018.11.17 |
[ Vulkan 연구 ] Memory Management Basic (4) | 2018.11.13 |
[ Vulkan 연구 ] Command Buffer & Levels (0) | 2018.11.12 |