반응형
지난 글(#5)에서 우리는 Vulkan에서 GPU 메모리를 관리하고, 버퍼나 이미지를 생성하고, 이를 GPU 메모리에 할당하는 기초를 다뤘습니다. 이제는 GPGPU의 핵심인 Compute 셰이더(Compute Shader)를 사용하기 위한 준비 단계로 넘어가겠습니다. Vulkan에서 Compute 셰이더를 실행하려면, 셰이더 코드를 SPIR-V로 컴파일하고, 이를 Compute 파이프라인(Compute Pipeline)에 등록한 뒤, 디스크립터(Descriptor)를 통해 버퍼, 이미지 등 자원을 셰이더에 연결해야 합니다.CUDA에서는 .cu 파일에 커널 코드를 작성하고 nvcc로 컴파일한 뒤 >> 표기법으로 커널을 호출하는 방식에 익숙할 것입니다. 하지만 Vulkan에서는 셰이더를 GLSL/HLSL로 ..
지난 글(#4)에서는 큐(Queue)와 커맨드 버퍼(Command Buffer) 개념을 정리하며, Vulkan이 GPU에 명령을 전달하는 독특한 방식을 살펴봤습니다. 이제 GPU에게 할 일을 시킬 수 있는 준비는 되었지만, 정작 우리가 처리할 데이터(배열, 이미지 등)를 GPU 메모리에 올려놓는 과정은 아직 다루지 않았습니다. 이번 글에서는 Vulkan 메모리 관리의 기초인 메모리 할당, 버퍼(Buffer), 이미지(Image) 객체를 다뤄보겠습니다.CUDA를 사용해보신 분이라면 cudaMalloc과 cudaMemcpy 정도로 GPU 메모리 관리가 비교적 단순했다는 기억이 있을 겁니다. 반면 Vulkan에서는 메모리 할당이 좀 더 “수작업”에 가깝고, 어떤 메모리 타입을 쓸지 직접 결정하고, 버퍼나 이미..
지난 글(#3)에서는 물리 디바이스를 골라서 로지컬 디바이스를 만들고, 큐를 확보하는 단계까지 진행했습니다. 이제 GPU에 작업을 시키기 위해서는 명령(Commands)들을 모아둘 그릇이 필요한데, Vulkan에서는 이를 "커맨드 버퍼(Command Buffer)"라고 부릅니다. 이번 글에서는 커맨드 버퍼를 다루는 법과 큐에 이 버퍼를 제출(Submit)하는 과정을 살펴보겠습니다. 또한 CUDA의 스트림(Stream) 개념과 비교하여 Vulkan 방식이 어떤 점에서 다른지 이해해봅시다.왜 커맨드 버퍼인가?간단히 말해, 커맨드 버퍼는 GPU에 내릴 명령을 모아둔 리스트입니다. 이 리스트를 나중에 큐(Queue)에 제출하면, GPU가 순서대로 실행하게 됩니다. 이런 구조는 단순히 함수 호출로 GPU를 동작시..
왜 이렇게 복잡할까?CUDA에 익숙한 분이라면 cudaSetDevice() 하나로 GPU를 선택하고, 바로 커널을 실행했던 기억이 있을 겁니다. 하지만 Vulkan은 조금 다릅니다. Vulkan은 다소 “하드코어”한 API라 할 수 있습니다. CUDA가 “GPU는 NVIDIA 것이고, 나머지는 다 내가 알아서 할게”라고 말해주는 친절한 셰프라면, Vulkan은 “냉장고는 저쪽, 칼은 여기, 조리대는 저기 있으니 필요한 걸 직접 꺼내서 써”라고 말하는 요리학원 선생님 같은 느낌이에요. 초반에 해야 할 준비가 많지만, 그만큼 다양한 하드웨어와 상황에 대처할 수 있는 큰 자유를 줍니다.물리 디바이스(Physical Device) 열람하기인스턴스를 만든 상태라면, 이제 시스템에 장착된 GPU 목록(물리 디바이스..
환경 설정이전 글(#1)에서 Vulkan을 GPGPU용으로 활용할 수 있다는 개념적 소개를 했습니다. 이제 실제 코드를 다루려면 환경이 제대로 갖춰져야 합니다. Ubuntu를 예로 들어 Vulkan SDK 설치, 드라이버 설정, CMake 및 기타 툴 설치 방법을 정리하고, Windows 사용자를 위한 간단한 가이드도 제공하겠습니다. 또한 CUDA 경험자들이 Vulkan 환경 구축을 이해하기 쉽도록 CUDA와의 차이점도 다시 상기시켜드리겠습니다.Ubuntu에서 Vulkan 환경 설정1. GPU 드라이버 설치:NVIDIA의 경우:sudo apt updatesudo ubuntu-drivers devicessudo ubuntu-drivers autoinstallAMD/Intel의 경우에는 Mesa 드라이버가 ..
들어가며많은 개발자들이 GPU를 활용한 병렬 연산(GPGPU)에 대해 관심을 가지고 있습니다. 일반적으로 GPGPU를 떠올리면 가장 먼저 CUDA를 연상하는 경우가 많습니다. NVIDIA GPU 상에서 폭넓은 지원과 고성능 라이브러리를 제공하는 CUDA는 확실히 GPGPU 분야의 강자입니다. 그렇다면 Vulkan은 어떨까요? Vulkan은 Khronos 그룹이 정의한, 차세대 저수준(low-level) 그래픽 및 컴퓨팅 API로 잘 알려져 있습니다. 흔히 “OpenGL의 다음 세대 솔루션”이라고 부르며, 높은 이식성과 멀티플랫폼 지원을 장점으로 합니다. 그러나 Vulkan은 단순히 그래픽 렌더링뿐만 아니라, GPGPU 연산(Compute Shader)에도 활용할 수 있는 범용 플랫폼이기도 합니다. 이 시..
C++20에서 std::chrono 라이브러리에 부분적으로 시간대(time zone)와 달력을 지원한 이후, C++23에서는 시간 처리 기능이 더욱 강화되었습니다. 특히, std::chrono에 utc_clock, tai_clock, file_clock와 같은 새로운 시간 기준이 도입되고, 윤초(Leap Second) 처리 개선 등의 기능이 추가되었습니다. 이번 글에서는 C++23에서 std::chrono 라이브러리가 어떻게 확장되었는지, 그리고 이전 버전과 비교하여 어떠한 개선점이 있는지 알아보겠습니다.새로운 시간 기준(Clocks) 도입C++23에서는 기존의 system_clock, steady_clock, high_resolution_clock 외에도 다양한 시간 기준이 추가되었습니다. 이를 통해 ..
C++23에서는 std::optional 타입에 모나딕(Monadic) 연산들을 추가하여 함수형 스타일의 체이닝(chaining)과 에러 처리를 더욱 편리하게 만들어주는 새로운 기능들이 도입되었습니다. 이번 글에서는 std::optional의 모나딕 연산(transform, transform_or, and_then, or_else)과 같은 기능의 개념과 사용법, 그리고 이전 버전과 비교하여 어떻게 개선되었는지 알아보겠습니다.std::optional의 모나딕 연산이란 무엇인가요?C++17에서 도입된 std::optional은 값이 존재할 수도 있고 존재하지 않을 수도 있는 상황을 안전하고 명확하게 처리하기 위한 타입입니다. 하지만 C++17에서는 std::optional에 대한 체이닝이나 함수 적용이 불편..
C++23에서는 컴파일러에게 특정 코드 경로가 절대 도달하지 않을 것임을 알리는 새로운 함수인 std::unreachable()가 도입되었습니다. 이번 글에서는 std::unreachable()의 개념과 사용법, 그리고 이전 버전과 비교하여 어떻게 개선되었는지 알아보겠습니다. std::unreachable()란 무엇인가요?std::unreachable()는 코드 상에서 절대 실행될 수 없는 경로임을 컴파일러에 알려주는 함수입니다. 이는 정의되지 않은 동작(Undefined Behavior)을 발생시키며, 컴파일러가 이 정보를 활용하여 해당 코드 경로를 제거하거나 최적화할 수 있게 합니다. 예를 들어, switch 문의 default 분기가 절대 발생하지 않는 경우나 특정 조건이 항상 참이라 이외의 경로로..
C++23에서는 범위(Range) 라이브러리를 더욱 풍성하게 만들기 위해 std::ranges::to 함수 템플릿이 도입되었습니다. 이번 글에서는 std::ranges::to의 개념과 사용법, 그리고 이전 버전과 비교하여 어떻게 개선되었는지 알아보겠습니다.std::ranges::to란 무엇인가요?C++20에서 범위(Range) 라이브러리가 도입되면서, 파이프라인 형태로 뷰(View)나 어댑터(Adapter)를 조합하여 데이터를 변환, 필터링, 슬라이싱하는 것이 가능해졌습니다. 하지만 변환된 범위를 최종적으로 컨테이너로 재수집하는 과정은 여전히 수동으로 작성해야 했습니다. C++23의 std::ranges::to는 이러한 변환 결과를 간단한 한 줄의 코드로 원하는 컨테이너로 모아주는 유틸리티 함수 템플릿입..