반응형
과거 C++ 템플릿 프로그래밍에서 타입 제약을 표현하기 위해 사용되던 기법 중 하나가 바로 SFINAE(Substitution Failure Is Not An Error)였습니다. 이는 템플릿 인자의 대입 과정에서 타입이 맞지 않을 경우 에러 대신 다른 오버로드를 시도하는 기법으로, 조건부로 템플릿을 선택하는 메타프로그래밍 트릭이었습니다.그러나 SFINAE는 코드가 복잡해지고, 컴파일 에러 메시지가 난해해진다는 단점이 있었습니다. 모던 C++20에서는 Concepts를 통해 이 문제를 해결했습니다. Concepts는 템플릿 인자에 대한 명확한 제약 조건을 선언적으로 표현할 수 있어 코드 가독성과 유지보수성, 그리고 에러 진단을 크게 개선합니다.관련 참고 자료:SFINAEConcepts (C++20)과거:..
과거 C++98/03 시절, 문자열 형식 지정 출력은 주로 C 표준 라이브러리 함수를 이용했습니다. printf 계열 함수들은 간단히 사용할 수 있지만, 타입 미스매치 문제나 서식 문자열 관리가 번거로운 단점이 있었습니다. 예를 들어 %d, %f, %s 등의 포맷 지정자가 실제 매개변수와 불일치할 경우 런타임 버그가 발생할 수 있으며, 이는 디버깅하기도 까다롭습니다.모던 C++에서는 이러한 문제를 해결하기 위해 C++20부터 std::format 함수를 도입했습니다. 이는 타입 안전하고, Python의 f-string과 유사한 형식 지정 문법을 제공하며, 가독성과 유지보수성을 크게 향상시킵니다.관련 참고 자료:std::format (C++20)과거: printf 계열 함수의 문제점printf는 서식 문자..
과거 C++98/03 시절에는 문자열 처리를 위해 C-Style 문자열(char*)을 직접 다루는 경우가 많았습니다. 그러나 C-Style 문자열은 널 종단 문자('\0')를 통해 문자열의 끝을 인식하고, 이를 다루는 과정에서 범위 초과, 메모리 누수, 버퍼 오버플로우 같은 위험이 상존했습니다. 또한 문자열 조작을 위해 std::strlen, std::strcpy 등 C 표준 라이브러리 함수를 반복적으로 사용하는 것은 번거롭고 오류를 내기 쉬운 방식이었습니다.모던 C++에서는 이러한 문제를 해결하기 위해 std::string과 C++17 이후의 std::string_view를 활용할 수 있습니다. 이로써 문자열 처리가 안전하고 직관적이며, 성능까지 고려한 형태로 진화했습니다.관련 참고 자료:std::st..
초창기 C++에서는 컨테이너를 순회하기 위해 전통적인 for 루프나 반복자(iterator)를 명시적으로 사용하는 패턴이 흔했습니다. 이런 방식은 인덱스나 반복자 관리에 번거로움이 있었고, 컨테이너 타입이 바뀌면 루프 조건을 바꾸는 등 유지보수가 어려웠습니다.모던 C++에서는 이러한 문제를 해소하기 위해 range-based for 루프와 C++20 Ranges 라이브러리가 등장했습니다. range-based for 루프를 통해 컨테이너 순회를 단순화하고, Ranges 라이브러리를 사용하면 필터링, 변환 등의 파이프라인 스타일 알고리즘을 선언적으로 표현할 수 있습니다. 이로써 코드 가독성과 유지보수성이 크게 향상됩니다.관련 참고 자료:Range-based for loopC++20 Ranges 라이브러리과..
과거 C++98/03 시절에는 정적 상수를 정의할 때 매크로를 사용하는 경우가 흔했습니다. 매크로는 전처리 단계에서 단순한 텍스트 치환을 수행하므로, 타입 정보가 없고 디버깅도 까다롭다는 문제가 있었습니다. 또한 범위(scope) 개념이 없어 어디서나 무분별하게 확장되며, 심지어 이름 충돌 문제도 야기할 수 있었습니다.모던 C++에서는 이러한 문제를 해결하기 위해 constexpr, const 정적 상수, 그리고 enum class를 적극적으로 활용할 수 있습니다. 이를 통해 타입 안전성과 가독성을 향상시키고, 컴파일 시간 상수 평가를 통한 성능 최적화도 기대할 수 있습니다.관련 참고 자료:constexpr specifierenum class과거: 매크로 상수의 문제점C-Style 매크로를 통해 상수를 ..
과거 C++98/03 시절, 정적 크기를 갖는 C-Style 배열은 흔하게 사용되었지만, 실제로는 다양한 문제를 안고 있었습니다. 배열의 크기를 코드 곳곳에 명시해야 하거나, 함수 인자로 전달할 때 크기 정보를 잃기 쉽고, 범위 초과 액세스를 검증하기 어렵다는 점 등이 대표적입니다. 이러한 방식은 대규모 프로젝트에서 메모리 안전성을 저해하고, 유지보수를 어렵게 만들었습니다.모던 C++에서는 이 문제를 해결하기 위해 여러 대안들이 등장했습니다. std::array는 정적 크기 배열을 안전하게 감싸며, std::vector는 동적 크기 배열을 편리하게 관리하고, C++20의 std::span은 기존 배열이나 컨테이너의 뷰(view) 역할을 하여 범위 정보를 담은 인터페이스를 제공합니다.관련 참고 자료:std..
2025년 현재, 모던 C++ 개발자는 더 이상 std::auto_ptr를 사용하는 모습을 보기 어렵습니다. auto_ptr는 C++98/03 시절 스마트 포인터의 초기 시도로 등장했으나, 그 독특하고 혼란스러운 소유권 전이(transfer) 방식으로 인해 많은 문제를 야기했습니다. 결국 C++11 이후 auto_ptr는 사용이 권장되지 않는(deprecated) 상태가 되었고, C++17에서는 완전히 제거되었습니다.이 글에서는 과거에 auto_ptr가 어떻게 사용되었는지, 그리고 그것이 어떤 문제를 일으켰는지 살펴봅니다. 이후 std::unique_ptr 및 std::shared_ptr가 등장함으로써 C++ 메모리 관리가 어떻게 개선되었는지, 그리고 이 변화가 왜 필수적이었는지 분석하겠습니다.관련 참고..
기존 DQN에서는 모든 경험을 동일한 확률로 샘플링합니다. 그러나 강화학습에서는 특정 경험(transition)이 학습 초기에는 별로 도움이 안 되지만, 나중에 정책이 개선되면서 가치가 달라지거나, 에이전트가 특정 상황에서 큰 TD 오차(Temporal-Difference Error)를 낼 경우 그 경험이 정책 개선에 더 크게 기여할 수 있습니다.우선순위 경험 리플레이(PER)의 핵심 아이디어는 TD 오차가 큰(즉, 현재 네트워크의 예측과 실제 타겟 간 차이가 큰) 경험을 더 자주 샘플링하는 것입니다. 이를 통해 에이전트는 정책 개선에 유용한 경험을 빠르게 재학습하고, 경험 데이터 활용 효율을 높일 수 있습니다.참고자료:Schaul et al., 2016. "Prioritized Experience Re..
안녕하세요! 지난 글에서는 OpenCL을 활용한 이미지 처리 예제를 다루며, 실제로 GPU 가속의 이점을 경험해봤습니다. 이제부터는 좀 더 깊은 주제로 들어가, 성능 최적화(Performance Optimization)에 대한 기본 개념을 살펴보려 해요. 입문자 수준에서 모든 최적화를 다루기는 어렵지만, 워크그룹(work-group) 설정, 메모리 접근 패턴 개선, 그리고 프로파일링(profiling) 도구 활용으로 성능을 개선할 수 있는 아이디어를 얻을 수 있습니다.이번 글에서는 다음 내용을 다룹니다.워크아이템(work-item), 워크그룹(work-group) 개념과 성능 관계메모리 계층(global, local, private memory)과 접근 패턴 최적화프로파일링을 통한 병목 지점 확인CUDA..
이번 글에서는 CMake를 사용하여 SIMD(Single Instruction, Multiple Data) 기반의 응용 프로그램을 구성하고 빌드하는 방법을 더욱 자세히 알아보겠습니다. SIMD는 데이터 병렬 처리를 통해 성능을 향상시키는 기술로, 멀티미디어 처리, 신호 처리, 과학 계산 등 다양한 분야에서 활용됩니다. 이번 글에서는 다양한 운영체제, CPU 아키텍처, 컴파일러에 따른 컴파일러 플래그와 옵션 설정 방법을 자세히 살펴보고, 크로스 빌드 상황에서 필요한 설정과 라이브러리, 툴에 대해서도 알아보겠습니다. 또한, 조건부 빌드의 다양한 사례를 통해 실전에서의 활용 방법을 제시하겠습니다.SIMD와 CMake의 통합SIMD 명령어 집합은 CPU 아키텍처와 세대에 따라 다르며, 이를 활용하기 위해서는 컴..