반응형
안녕하세요! 지난 글들에서 OpenCL의 기본 사용법을 어느 정도 파악하셨다면, 이제는 조금 더 현대적인 C++ 문법과 래퍼(wrapper) 라이브러리를 활용해 코드를 깔끔하게 정리하는 방법을 살펴보려고 해요. OpenCL 기본 API는 C 스타일 함수들로 구성되어 있고, 초기화 및 에러 처리 로직이 장황해지는 경우가 많은데, C++20/23 기능을 적극 활용하면 가독성과 유지보수성을 크게 높일 수 있습니다.이번 글에서는 다음 내용을 다룹니다.OpenCL C++ Wrapper(CL.hpp) 라이브러리 소개스마트 포인터, 범위 기반 for문, 구조적 바인딩 등 C++20/23 기능 활용에러 처리와 RAII(Resource Acquisition Is Initialization) 패턴 적용CUDA와 비교: C..
앞선 글에서 우리는 C++에서 PyTorch 텐서를 생성하고 연산하며, TorchScript 모델을 C++에서 로드하는 방법, 그리고 pybind11을 통해 C++ 함수를 Python에서 호출하는 방법까지 살펴보았습니다. 이제 한 단계 더 나아가 C++과 Python 사이에서 텐서를 자유롭게 주고받는 방법을 다뤄보겠습니다.이 과정은 다양한 시나리오에서 유용합니다. 예를 들어,Python에서 전처리한 입력 데이터를 C++ 모델 로직에 전달하고 싶을 때C++에서 계산한 텐서를 Python에서 시각화하거나 후처리하고 싶을 때Python에서 추론 로직 일부를 C++로 구현하여 성능을 향상시키고, 그 결과를 다시 Python으로 반환할 때이 글에서는 pybind11과 LibTorch를 활용해 C++과 Python..
안녕하세요! 지난 글에서는 OpenCL 커널 작성법과 빌드 과정을 살펴보았습니다. 이제 커널에서 다룰 데이터가 어떻게 GPU나 CPU 디바이스 메모리에 올라가는지, 즉 OpenCL 메모리 모델과 그 핵심 요소인 버퍼(Buffer)와 이미지(Image)에 대해 알아볼 차례예요. 또한 커널에 파라미터(인자)를 전달하는 다양한 패턴에 대해서도 간단히 짚어보겠습니다.이번 글에서는 다음 내용을 다룹니다.OpenCL 메모리 모델 개요버퍼(Buffer)와 이미지(Image)의 특징과 사용 예커널 파라미터 설정 방법 심화CUDA의 메모리 관리 방식과 비교추가 참고 자료 (유튜브)1. OpenCL 메모리 모델 개요OpenCL 프로그램에서는 호스트(Host)가 디바이스(Device)에 연산을 시킵니다. 이 때, 데이터를 ..
지난 글에서는 2D 데이터 처리와 비동기 스트림(Asynchronous Streams)을 통해 Host와 Device 간 연산이 겹칠 수 있음을 확인했습니다. 이제는 GPU 메모리 계층을 살짝 들여다보고, 성능 최적화를 위해 왜 이러한 구조가 존재하는지 알아볼 차례입니다. 오늘 다룰 주제는 Shared Memory와 Constant Memory라는 특별한 메모리 공간들입니다. 이들은 단순한 글로벌 메모리(Global Memory) 접근보다 훨씬 더 빠르거나 특정 상황에서 효율적인 접근을 가능하게 해줍니다.메모리 계층 구조 이해하기GPU 메모리는 단순하지 않습니다. 성능을 극대화하기 위해 다양한 메모리 종류가 존재합니다.Global Memory(전역 메모리): 우리가 지금까지 cudaMalloc로 할당한 ..
이번 글에서는 지금까지 배운 스레드/블록/그리드 개념을 2차원 데이터에 적용하고, GPU의 비동기(Asynchronous) 기능을 살짝 맛보며 최적화를 향한 첫걸음을 내딛어보겠습니다. 이미지 처리나 행렬 연산 같은 2D 데이터 처리는 실제 GPU 활용 분야에서 매우 흔하고도 중요한 영역입니다. 또한 비동기 스트림을 활용하면 Host와 Device 사이의 작업을 겹치게 만들어 전체 처리 시간을 단축할 수 있다는 점을 알아볼 것입니다.2D 데이터 처리를 위한 블록/그리드 설정지금까지는 1차원 데이터(예: 벡터)에 대한 처리를 주로 다뤘습니다. 하지만 이미지(2D 배열)나 행렬을 다룬다면 2차원적으로 스레드와 블록을 배치하는 것이 직관적일 수 있습니다.2D 스레드 인덱스 계산 예제예를 들어, M x N 크기의..
안녕하세요! 지난 글에서 OpenCL 플랫폼과 디바이스 개념을 이해하고, 원하는 디바이스를 선택하는 방법까지 살펴봤습니다. 이제 본격적으로 커널(Kernel) 작성과 빌드 과정을 알아볼 차례예요. OpenCL 커널은 실제로 GPU나 CPU 등 디바이스에서 병렬 실행되는 코드로, 우리가 가속하고 싶은 연산의 핵심 부분이라고 할 수 있죠.이번 글에서는 다음 내용을 다룹니다.OpenCL 커널 기본 문법 소개호스트 코드에서 커널 빌드 방법 복습 및 확장인자 전달 및 메모리 관리 구조 이해CUDA 커널과 비교해 보는 코드 작성 차이점참고할만한 유튜브 자료 링크앞선 글에서 kernel.cl 파일 안에 간단한 add_one 커널을 작성해봤는데, 이번 글에서는 이보다 조금 더 다양한 형태의 커널 코드를 다뤄보면서 기본..
안녕하세요, 지난 글에서 OpenCL 개발환경을 준비하고 “Hello OpenCL!” 예제를 통해 간단한 프로그램을 실행하는 과정을 살펴봤어요. 이번 글에서는 본격적으로 OpenCL의 큰 그림을 더 명확히 그려볼게요. OpenCL은 플랫폼(Platform)과 디바이스(Device)라는 개념을 통해 다양한 하드웨어 리소스를 관리하고, 이를 프로그래머가 직접 선택하고 제어할 수 있는 구조를 가지고 있습니다. 쉽게 말해, 플랫폼은 특정 벤더나 특정 드라이버 환경을 대표하는 개념이고, 디바이스는 실제 연산을 수행할 수 있는 하드웨어(GPU, CPU, FPGA 등)를 가리켜요. CUDA가 NVIDIA GPU 하나를 전제로 간단한 API로 리소스를 추상화했다면, OpenCL은 다양한 하드웨어를 유연하게 다루기 위해..
안녕하세요! 이번 포스팅부터 OpenCL(Open Computing Language)을 활용해 GPU 가속 프로그래밍을 시작하려는 입문자 분들을 위해 총 10편에 걸친 시리즈를 진행하려고 해요.OpenCL은 GPU, CPU, FPGA 등 다양한 디바이스에서 병렬 계산을 지원하는 오픈 표준인데요. 흔히 비교되는 CUDA가 NVIDIA GPU를 염두에 둔 전용 기술이라면, OpenCL은 다양한 벤더와 디바이스에서 유연하게 활용할 수 있는 특징이 있어요. “어? 난 이미 CUDA에 좀 익숙한데?” 하는 분들도, 여기서 OpenCL을 배워두면 훨씬 넓은 하드웨어 지원 범위를 가질 수 있게 되는 셈입니다.이번 첫 글에서는 다음과 같은 내용을 담았습니다.OpenCL 개발 환경 준비(Ubuntu, Windows 참조..
지난 글에서는 Host-Device 메모리 전송, cudaMalloc, cudaMemcpy 등을 활용하여 벡터 덧셈 예제를 성공적으로 구동해봤습니다. 이제 GPU 병렬 프로그래밍의 핵심인 스레드, 블록, 그리고 그리드 개념을 파고들 차례입니다. 이 개념들은 GPU 상에서 대규모 병렬 연산을 구성하는 뼈대와 같습니다. 오늘은 스레드와 블록, 그리고 이들을 묶어 전체 문제를 분할하는 방식인 그리드(Grid)에 대해 차근차근 살펴보며, "내가 원하는 만큼 병렬화"하는 방법을 이해해보겠습니다.스레드(Thread)란?스레드는 GPU 병렬 연산의 최소 실행 단위입니다. CPU에서도 멀티스레딩을 통해 병렬 처리를 하지만, GPU에서는 수백만 개의 스레드를 가볍게 실행할 수 있습니다. 각각의 스레드는 독립적으로 실행되..
이제 우리는 Host(CPU)와 Device(GPU) 코드 구조를 이해하고, 간단한 커널 호출 예제를 통해 GPU 코드가 어떻게 동작하는지 살펴봤습니다. 이번 글에서는 실제로 데이터를 GPU로 보내고, 연산한 뒤 다시 결과를 가져오는 과정을 좀 더 구체적으로 다뤄볼 예정입니다. 즉, Host Device 메모리 전송(cudaMemcpy) 및 메모리 할당(cudaMalloc) 방법을 배우고, 이를 활용한 간단한 벡터 덧셈 예제를 통해 GPU 병렬 연산의 기본을 체험해보겠습니다.Host와 Device 메모리 관리의 기본앞서 말했듯 Host와 Device는 별개의 메모리 공간을 사용합니다. 이는 마치 서로 다른 섬에 사는 두 존재가 다리를 통해 상자를 옮기는 상황과 비슷합니다. 여기서 상자는 데이터, 다리는..