본문 바로가기
개발 가이드/AI 개발

[AI 개발] 2. C++와 ML/AI 완전 가이드

by 플로거 2026. 7. 19.

ML / AI 고성능 연산 언어 가이드

C++ 완전 가이드

C++가 ML·AI 시스템에서 담당하는 역할부터 CMake 빌드, 배열 연산, Python 바인딩, 추론 엔진, 설계와 운영 검증까지 한 번에 정리합니다.

  • CMake
  • 텐서 연산
  • pybind11
  • ONNX Runtime
  • TensorRT
  • 성능 검증
핵심 요약
Python은 모델 실험과 애플리케이션 개발에 강하고, C++는 실제 연산 코어와 런타임 성능에 강합니다. 두 언어를 경쟁 관계가 아니라 역할을 나눠 사용하는 조합으로 이해하는 것이 중요합니다.

1. C++와 ML/AI

C++는 텐서 연산, CUDA 바인딩, 추론 런타임, 모델 서빙 엔진처럼 성능이 중요한 ML·AI 코어 영역에 사용됩니다. PyTorch, TensorFlow, ONNX Runtime 같은 도구 역시 내부의 고성능 영역에서 C++와 GPU 가속 기술을 활용합니다.

영역 C++의 역할
연산 코어 행렬 곱, 컨볼루션, 메모리 최적화
하드웨어 가속 CUDA, ROCm, NPU SDK 연동
런타임 저지연 추론 서버와 엣지 배포
바인딩 Python에서 호출 가능한 네이티브 확장
Python
모델 실험
모델 변환
ONNX
C++ 런타임
고속 추론
운영
관측·확장

2. 빌드 환경

현대 C++ 프로젝트는 CMake로 빌드 구성을 관리하는 방식이 일반적입니다. 개발과 운영 환경의 옵션을 분리하고, 의존성과 컴파일 옵션을 target 단위로 관리하는 것이 좋습니다.

Bash
mkdir ml-core && cd ml-core
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release

기본 CMakeLists.txt

CMake
cmake_minimum_required(VERSION 3.20)
project(ml_core LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_library(mlcore STATIC
    src/vector_add.cpp
)

target_include_directories(mlcore
    PUBLIC
        ${CMAKE_CURRENT_SOURCE_DIR}/include
)
티스토리 코드 블록 처리
코드 내부의 <, >, & 문자는 HTML 안전 문자로 변환했습니다. 따라서 HTML 모드에 붙여 넣어도 템플릿 태그처럼 해석되지 않습니다.

3. 배열 연산

단순한 벡터 연산도 메모리 접근 패턴과 병렬화 전략에 따라 성능 차이가 커집니다. 먼저 정확하고 읽기 쉬운 구현을 작성한 뒤 프로파일링 결과를 기준으로 최적화하세요.

vector_add.cpp
#include <stdexcept>
#include <vector>

std::vector<float> add(
    const std::vector<float>& a,
    const std::vector<float>& b
) {
    if (a.size() != b.size()) {
        throw std::invalid_argument("vector sizes must match");
    }

    std::vector<float> out(a.size());

    for (std::size_t i = 0; i < a.size(); ++i) {
        out[i] = a[i] + b[i];
    }

    return out;
}

성능을 확인할 항목

  • 반복문 내부에서 불필요한 메모리 할당이 발생하는지 확인합니다.
  • 데이터가 연속된 메모리에 배치되는지 확인합니다.
  • 복사 대신 참조 또는 이동을 사용할 수 있는지 검토합니다.
  • SIMD나 GPU 병렬화가 실제 병목 개선에 도움이 되는지 측정합니다.
주의
측정 없이 컴파일러 옵션이나 병렬화를 먼저 적용하면 코드 복잡도만 커질 수 있습니다. 프로파일링으로 병목 구간을 확인한 뒤 최적화하세요.
반응형

4. Python 바인딩

pybind11을 사용하면 C++로 작성한 고성능 함수를 Python에서 자연스럽게 호출할 수 있습니다. 모델 개발자는 Python 인터페이스를 사용하고, 성능 핵심 로직은 C++ 라이브러리로 분리할 수 있습니다.

bindings.cpp
#include <pybind11/pybind11.h>

namespace py = pybind11;

int add(int a, int b) {
    return a + b;
}

PYBIND11_MODULE(mlcore, module) {
    module.doc() = "High-performance ML core extension";
    module.def(
        "add",
        &add,
        py::arg("a"),
        py::arg("b"),
        "Fast addition implemented in C++"
    );
}
Python
import mlcore

result = mlcore.add(10, 20)
print(result)  # 30
바인딩 경계에서는 예외 변환, 문자열 인코딩, 배열 복사, GIL 처리, ABI 호환성을 확인해야 합니다. 대용량 배열은 불필요한 복사가 발생하지 않도록 설계하는 것이 중요합니다.

5. 추론 엔진

운영 환경에서는 ONNX Runtime, TensorRT, Triton Inference Server 같은 런타임과 C++ API를 조합해 추론 지연 시간을 줄입니다. Python으로 모델을 만든 뒤 ONNX 등의 형식으로 변환하고, C++ 런타임에서 로드해 서비스하는 흐름이 일반적입니다.

기술 특징 적합한 환경
ONNX Runtime 여러 프레임워크의 모델을 공통 런타임으로 실행 CPU·GPU 범용 추론
TensorRT NVIDIA GPU 중심의 그래프 및 정밀도 최적화 저지연 GPU 추론
Triton Inference Server 다중 모델, 동적 배치, 메트릭, 모델 저장소 지원 서버 기반 모델 서빙
  • GPU 메모리 복사와 배치 크기는 추론 성능의 핵심 변수입니다.
  • FP32, FP16, INT8 등 정밀도 선택에 따라 성능과 정확도가 달라집니다.
  • 모델 세션을 요청마다 생성하지 않고 재사용하는 구조가 필요합니다.

6. C++ 실무 설계

C++는 성능 코어와 바인딩 레이어를 분리해야 합니다. RAII, ownership, ABI 경계, CMake target 구성을 명확히 잡아야 Python 및 서빙 런타임과 안정적으로 연결할 수 있습니다.

결정 지점 확인 질문 실무 기준
경계 자주 바뀌는 코드와 핵심 연산이 섞여 있는가? 입출력, 설정, 외부 연동과 연산 코어를 분리합니다.
상태 상태가 어디서 생성되고 소멸하는가? 소유자와 수명 주기를 코드 구조로 드러냅니다.
장애 실패 시 호출자가 무엇을 받는가? timeout, fallback, error contract를 먼저 정의합니다.

7. 운영 기준

운영 성능은 알고리즘 복잡도뿐 아니라 memory allocation, cache locality, SIMD 효율과 GPU 전송 비용의 영향을 받습니다.

  • RAII 기반으로 메모리, 파일, 스레드, GPU 리소스를 관리합니다.
  • ASAN, UBSAN, TSAN을 개발 및 검증 파이프라인에 포함합니다.
  • 성능 핵심 함수는 microbenchmark로 기준값을 관리합니다.
  • ABI 경계와 공유 라이브러리 버전을 명확히 관리합니다.
Sanitizer 빌드
cmake -S . -B build-asan \
  -DCMAKE_BUILD_TYPE=Debug \
  -DCMAKE_CXX_FLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer"

cmake --build build-asan
ctest --test-dir build-asan --output-on-failure

8. 검증 전략

고성능 C++ 코드는 정상 동작 테스트만으로 충분하지 않습니다. sanitizer, benchmark, fuzzing, ABI compatibility test를 함께 운영해야 메모리 오류와 성능 회귀를 조기에 발견할 수 있습니다.

품질 축 검증 방법 완료 기준
정확성 정상·경계·실패 케이스 자동화 핵심 시나리오가 반복 실행돼도 동일하게 통과
회귀 방지 버그 수정 시 동일 케이스를 테스트로 유지 같은 장애가 다시 배포되지 않음
메모리 안전성 ASAN, UBSAN, Valgrind 누수와 정의되지 않은 동작이 검출되지 않음
성능 microbenchmark와 기준값 비교 허용 범위를 넘는 지연 또는 처리량 저하가 없음
운영성 로그, 메트릭, 알림, 장애 시나리오 문제 발생 시 원인 추적 경로가 존재

마무리

ML·AI 프로젝트에서 C++를 도입할 때는 전체 시스템을 다시 작성하기보다 실제 병목이 발생하는 연산 코어와 추론 런타임부터 분리하는 접근이 현실적입니다. Python의 생산성과 C++의 성능을 결합하고, 빌드·바인딩·관측·검증 체계를 함께 설계해야 운영 가능한 시스템이 됩니다.

핵심 정리
  • C++는 ML·AI의 고성능 연산과 추론 런타임에 적합합니다.
  • CMake target 중심으로 빌드와 의존성을 관리합니다.
  • Python 바인딩에서는 복사, 예외, GIL, ABI 경계를 확인합니다.
  • 최적화는 프로파일링과 벤치마크 결과를 기준으로 진행합니다.
  • Sanitizer, fuzzing, 성능 회귀 테스트를 CI/CD에 포함합니다.

원문: AI DevOps Korea C++ 가이드

반응형

댓글