주의 : 이 문서는 초심자 튜토리얼이 아닙니다. 기본 개념 정도는 안다고 가정합니다. 초심자는 [ 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 해서 사용할 수 있는 편리한 라이브러리입니다.

+ Recent posts