반응형
이전 글에서는 전략(Strategy) 패턴을 모던 C++ 관점에서 재해석하며, 상속 없이도 람다와 Concepts, std::expected, coroutine, Ranges, std::format 등을 활용해 알고리즘(전략)을 런타임에 교체 가능하게 하고, 비동기 처리나 로깅, 조건부 선택 등 다양한 상황에 쉽게 대응할 수 있음을 확인했습니다. 이번에는 Creational(생성) 패턴 중 하나인 추상 팩토리(Abstract Factory) 패턴을 다룹니다.추상 팩토리 패턴은 관련된 여러 객체(제품)들을 묶어 "제품군(family)"을 생성하는 인터페이스를 제공하는 패턴입니다. 전통적으로는 AbstractFactory 인터페이스와 구체 팩토리 클래스를 상속으로 정의하고, 각 제품(객체) 생성 메서드를 오..
이전 글에서는 상태(State) 패턴을 모던 C++ 관점에서 재해석하며, std::variant, std::visit, Concepts, std::expected, coroutine, Ranges, std::format 등을 활용해 상속 없이 값 기반 상태 머신을 구현하고, 조건부 전이, Undo/Redo, 비동기 처리, 로깅 등 다양한 요구사항에도 대응할 수 있음을 확인했습니다. 이제는 행동(Behavioral) 패턴 중 전략(Strategy) 패턴을 다룹니다.전략 패턴은 알고리즘 패밀리를 정의하고, 이를 교체 가능하게 하여 런타임에 다른 알고리즘을 선택할 수 있도록 하는 패턴입니다. 전통적으로는 Strategy 인터페이스와 ConcreteStrategy 클래스를 상속해 구현했지만, 이는 알고리즘 추가..
이전 글에서는 책임 연쇄(Chain of Responsibility) 패턴을 모던 C++ 관점에서 재해석하며, 상속 없이 람다와 함수 합성, std::expected, coroutine, Ranges, std::format 등을 활용해 요청 처리 파이프라인을 단순하고 유연하게 구현할 수 있음을 확인했습니다. 이제는 행동(Behavioral) 패턴 중 상태(State) 패턴을 다룹니다.상태 패턴은 객체가 내부 상태에 따라 서로 다른 행동을 수행하도록 하는 패턴입니다. 전통적으로는 State 인터페이스, ConcreteState 클래스를 상속해 상태별로 다른 메서드를 오버라이드하고, 상태 전이 시 상태 객체 교체 방식으로 구현했습니다. 이는 새로운 상태 추가 시 클래스 증가, 상태 전이 로직 분산, 유지보수..
이전 글까지 우리는 대부분의 GoF 패턴을 모던 C++ 관점에서 재해석해왔습니다. 이번에는 행동(Behavioral) 패턴 중 아직 다루지 않은 책임 연쇄(Chain of Responsibility) 패턴에 주목합니다.책임 연쇄 패턴은 한 요청이 처리될 수 있는 핸들러를 체인 형태로 연결하고, 요청이 들어오면 체인을 따라가며 처리 가능 한 핸들러를 찾는 구조를 만듭니다. 전통적으로는 핸들러 인터페이스와, setNextHandler() 메서드를 통해 다음 핸들러를 연결하는 구조를 취했지만, 이는 상속 기반 설계로 인한 클래스 증가와 유지보수 어려움을 야기합니다.C++20 이상에서는 Concepts로 요청/응답 인터페이스를 제약하고, 람다와 함수 합성으로 핸들러를 정의해 상속 없이 체인을 구성할 수 있습니다..
이전 글에서는 플라이웨이트(Flyweight) 패턴을 모던 C++ 관점에서 재해석하며, 상속 없이 값 기반 공유 로직을 단순히 구현하고, 조건부 처리, 비동기 로딩, 로깅, 에러 처리 등 다양한 요구에도 쉽게 대응할 수 있음을 확인했습니다. 이번에는 구조적 패턴 중 프록시(Proxy) 패턴을 다룹니다.프록시 패턴은 객체 접근을 제어하거나, 지연 로딩(Lazy Loading), 원격 호출(Remote Proxy), 캐싱(Caching), 권한 체크 등의 기능을 대리 객체를 통해 투명하게 추가하는 패턴입니다. 전통적으로는 상속 기반 인터페이스와 Proxy 클래스를 정의해 접근 로직을 구현했으나, 이는 클래스 증가, 유지보수 어려움, 에러 처리나 비동기 처리 시 복잡성을 초래합니다.C++20 이상에서는 Con..
안녕하세요! 지난 글에서는 디버깅과 프로파일링 기초를 다루며 OpenCL 프로그램을 더 안정적이고 효율적으로 다루는 방법을 살펴봤어요. 이제 거의 시리즈의 끝이 보이는데요. 이번 글에서는 한 시스템 내 여러 디바이스(여러 개의 GPU, CPU, 또는 이종 디바이스)를 동시에 활용하는 방법을 간략히 살펴볼 겁니다.CUDA는 보통 하나의 GPU를 다루는 경우가 많지만, OpenCL은 다양한 벤더, 다양한 하드웨어를 동시에 활용할 수 있는 아키텍처적 장점이 있어요. 예를 들어, 한 PC에 NVIDIA GPU와 Intel GPU, 그리고 CPU 디바이스까지 있을 때, 이들을 모두 활용해 연산을 나누어 처리할 수도 있습니다. 이번 글에서는 다음 내용을 다룹니다.여러 디바이스 선택 방법멀티 디바이스 컨텍스트(Con..
안녕하세요! 지난 글에서 성능 최적화 기초를 다루며 워크그룹 크기 조정, 메모리 접근 패턴 개선, 프로파일링의 중요성을 언급했습니다. 이번 글에서는 한 단계 더 나아가, OpenCL 프로그램을 디버깅하고 성능을 자세히 프로파일링하는 기본적인 방법을 살펴보려 합니다.디버깅과 프로파일링은 생각보다 중요한 영역입니다. 코드가 잘 동작한다고 생각했는데 결과가 이상하거나, 성능이 기대 이하일 수 있어요. 이때 단순히 코드를 쳐다보고 있는 것보다, 디버깅 툴이나 프로파일링 툴을 활용하는 것이 훨씬 효율적입니다.이번 글에서는 다음 내용을 다룹니다.디버깅 기초: 커널 실행 문제 파악, 에러 코드 확인프로파일링 툴 소개: 이벤트(event) 기반 타이밍, Nsight, Intel VTune 등호스트-디바이스 간 데이터 ..
이제 10개의 글에 걸친 “CUDA & Modern C++로 GPU 프로그래밍 시작하기” 시리즈를 마칠 시점입니다. 첫 글에서는 단순히 “Hello, GPU!”를 출력하는 예제부터 시작했지만, 이제는 Host-Device 메모리 관리, 스레드/블록/그리드 개념, 비동기 스트림, 메모리 계층(Shared/Constant), CMake 기반의 현대적 빌드, Modern C++ 기능 적용, 디버깅 및 프로파일링까지 다양한 주제를 맛보았습니다. 마지막으로 이 시리즈를 정리하며, 앞으로 여러분이 확장해나갈 수 있는 주제들을 안내하겠습니다.시리즈 정리환경 설정 & Hello GPU!: CUDA 개발환경(드라이버, 툴킷) 세팅 및 간단한 출력 예제를 통해 기본 틀을 잡았습니다.Host vs Device 코드 구조 이..
안녕하세요! 지난 글에서는 OpenCL을 활용한 이미지 처리 예제를 다루며, 실제로 GPU 가속의 이점을 경험해봤습니다. 이제부터는 좀 더 깊은 주제로 들어가, 성능 최적화(Performance Optimization)에 대한 기본 개념을 살펴보려 해요. 입문자 수준에서 모든 최적화를 다루기는 어렵지만, 워크그룹(work-group) 설정, 메모리 접근 패턴 개선, 그리고 프로파일링(profiling) 도구 활용으로 성능을 개선할 수 있는 아이디어를 얻을 수 있습니다.이번 글에서는 다음 내용을 다룹니다.워크아이템(work-item), 워크그룹(work-group) 개념과 성능 관계메모리 계층(global, local, private memory)과 접근 패턴 최적화프로파일링을 통한 병목 지점 확인CUDA..
이제 여기까지 왔습니다! 우리가 지금까지 다룬 내용을 바탕으로, 간단한 실전 예제를 통해 모든 개념을 종합해볼 시간입니다. 이번 글에서는 이미지 처리 예제를 선택하겠습니다. 이유는 다음과 같습니다:2D 데이터 처리(블록/스레드 2D 설정) 개념 확립Shared Memory나 Constant Memory를 활용해볼 수 있는 기회비동기 스트림으로 데이터 전송과 연산 오버랩 시도Modern C++ 빌드 및 언어 기능을 통한 코드 가독성 개선디버깅 및 프로파일링 연습“간단한 이미지 필터” 예제를 통해 실제 GPU 코드가 어떻게 구조화되고, 이전에 배운 개념들이 어떻게 융합되는지 살펴보겠습니다.실전 예제 개요: 간단한 블러(Blur) 필터 적용하기우리가 구현할 내용은 다음과 같습니다.Host에서 이미지를 로딩 (..