AI 프레임워크 개발자나 컴파일러 엔지니어가 새로운 레이어(연산 구조) 를 실험하거나 개발할 때,
실제로 하는 일은 — **“그 레이어를 구현할 임의의 커널 형태를 먼저 만들어서 완성해두는 것”**이야.
즉, 모델의 수학적 정의보다 ‘실행 가능한 커널 형태’를 우선 구현하는 거지.
이걸 조금 더 구체적으로 단계별로 풀면 이렇게 돼 👇
🔧 1️⃣ 새로운 레이어를 만든다는 건 곧 새로운 커널 패턴을 만든다는 뜻
예를 들어 “Conv2D + Channelwise Attention” 같은 새로운 연산을 연구한다고 해보자.
이걸 실제로 GPU에서 돌리려면,
- PyTorch나 TensorFlow에서의 수식 수준 구현 (prototype)
- 성능 한계 확인 (launch latency, memory, bandwidth)
- 커널화(kernelization) 단계로 넘어감
이때 커널화는 “임의의 CUDA/C++ 커널을 직접 구현”하거나,
기존 라이브러리(cuDNN, CUTLASS, cublasLt) 조합으로 비슷한 형태를 재구성하는 방식으로 진행된다.
즉, “새 레이어를 만든다” = “이 레이어가 실행될 최적의 커널 형태를 디자인한다.”
⚙️ 2️⃣ 커널 실험 구조의 기본 형태
엔지니어들은 일반적으로 이런 식으로 실험한다:
/ops/new_layer/
├─ kernels.cu # 실험용 커널 (CUDA)
├─ launcher.cu # 런처 (<<<grid, block>>> 설정, stream 관리)
├─ api.hpp # 함수 시그니처 정의 (C++)
├─ pybind.cpp # Python 바인딩
└─ test_new_layer.py # 성능/정확도 실험 스크립트
즉,
- “커널”은 완전히 정적 (고정된 쓰레드 구성, shared memory layout, tile size)
- “런처”는 커널 파라미터를 세팅해주는 C++ 코드
- “API”는 Python이나 컴파일러 상위 모듈에서 이 커널을 호출할 수 있게 연결
이렇게 임의의 커널 형태를 직접 설계하고, 필요한 만큼 튜닝한 뒤 고정시켜둔다.
🧠 3️⃣ 왜 임의로 “완성된 커널”을 만들어두는가
그 이유는 세 가지야:
| ① 실험 반복 효율성 | 매번 커널을 새로 컴파일하거나 런타임 JIT로 만들면 너무 느림 |
| ② 최적화 용이성 | 실제 실험은 tile 크기, thread block, memory access 패턴 조정이 핵심이므로 코드 수준 제어 필요 |
| ③ 재현성 | 동일한 환경에서 profiling/Nsight 분석을 반복하기 위해 커널 버전을 고정해야 함 |
즉, 논문이나 제품 개발 환경에서는 “이 레이어는 이 커널 구조로 구성되어 있다”라는 식으로
하드코딩된 최적 커널 세트를 미리 만들어 놓고, 그걸 실험에 사용해.
🔬 4️⃣ 연구자 / 엔지니어별 접근 차이
| ML 연구자 | PyTorch / TensorFlow로 수식 정의 | 수학적 아이디어 검증 |
| 커널 엔지니어 | CUDA/C++로 임의의 커널 구현 | 실제 실행 성능 검증 |
| 컴파일러 엔지니어 | 여러 커널을 후보로 등록 → 튜너/선택기로 자동화 | 커널 자동 선택 시스템 구축 |
즉, 네가 지금 하고 있는 graph_executor_v2의 CUDA backend 구조는
이 “커널 엔지니어 + 컴파일러 엔지니어” 역할의 교차점에 정확히 서 있어.
⚡ 5️⃣ 실제 실험 예시 (진짜 환경 그대로)
예를 들어 CUTLASS를 이용해서 “GEMM + Bias + SiLU”를 새로 실험하려면:
using Gemm = cutlass::gemm::device::Gemm<
float, cutlass::layout::RowMajor,
float, cutlass::layout::RowMajor,
float, cutlass::layout::RowMajor,
float, cutlass::arch::OpClassTensorOp,
cutlass::arch::Sm86,
cutlass::gemm::GemmShape<128, 128, 32>,
cutlass::gemm::GemmShape<64, 64, 32>,
cutlass::epilogue::thread::LinearCombinationBiasActivation<
float, 1, float, float, cutlass::epilogue::thread::SiLU
>
>;
→ 이렇게 하면, “이 커널이 수행할 타일링/에필로그 형태를 고정한 하나의 커널 엔진”이 생긴다.
이걸 여러 버전으로 튜닝해두고, 성능이 가장 좋은 걸 **‘기준 커널’**로 정한다.
🔩 6️⃣ 실제 배포 시에는?
실험 중 완성된 커널을 → 빌드 타임에 정적으로 링크하거나,
→ TensorRT / TVM / AITemplate 같은 컴파일러가 이걸 호출하도록 IR 규칙에 등록한다.
즉:
실험 단계: 다양한 커널 패턴 실험
컴파일러 단계: 최적 커널 선택 or 자동 튜닝
배포 단계: 해당 커널만 정적으로 삽입
🧩 요약
| 실험 초기 | 임의의 CUDA/C++ 커널을 직접 만들어 성능 테스트 |
| 실험 완료 | 가장 빠른 커널 구조를 고정 |
| 컴파일러 통합 | 그 커널을 코드젠 또는 런타임 선택 대상으로 등록 |
| 배포 | 이미 최적화된 커널을 정적으로 링크, 디바이스에 포함 |
즉, “새로운 레이어 개발”은 커널 패턴을 설계·완성하는 과정이며,
이후엔 그 커널이 컴파일러나 런타임의 선택지로 들어간다.
'dev_AI_framework' 카테고리의 다른 글
| graph_executor, 어떤 방식으로 graph_key, pool 의 분리, 재사용 확인 (0) | 2025.11.04 |
|---|---|
| AI Compiler — Role by Graph Type (정적 vs 동적 그래프 형태에 따른 AI 컴파일러의 역할 차이) (0) | 2025.10.29 |
| 지금까지 실행 파이프 라인 ( graph_capture, planner ... ) 향후 pattern matting 을 추가하기 위해 확인 (0) | 2025.10.29 |
| Graph Execution & Planning 과 CUDA Graph Capture & Stability 의 차이 (0) | 2025.10.28 |
| 단순 복붙, 각 부분 수정 필요함, 단 이는 최적화 단계에서, 일단 구현 먼저 다 하자 으쌰으쌰 (0) | 2025.10.28 |