백엔드 연산을 구현하면서 기초 지식을 다시 다지기
백엔드란?
아이디어: “수학 연산을 어디서 돌릴지”를 추상화한 층.
- CPU 백엔드 → numpy/Eigen 같은 걸로 계산
- GPU 백엔드 → CUDA 커널 + cuBLAS/cuSOLVER로 계산
코드에서 토글
xp = cupy if use_gpu else numpy # 공통 연산자(dot, exp, sum...)를 xp로 호출
흐름(GPU일 때):
- 호스트(Python/CPU)에서 **장치 메모리(GPU)**에 배열을 올림(H2D 복사)
- 연산 요청 → 커널/라이브러리 호출(cuBLAS, cuSOLVER…)
- 필요하면 결과를 CPU로 내림(D2H 복사)
→ 왕복을 줄이고 GPU에 “상주”시키는 게 핵심
BLAS가 뭐고, GEMM/GEMV는 뭔데?
BLAS는 “표준 선형대수 연산” 규격이고, CUDA에선 cuBLAS가 구현체
- Level-1 (벡터-벡터): AXPY( y ← a·x + y ), DOT(내적), NRM2(노름), SCAL(스칼라 곱)
- Level-2 (행렬-벡터): GEMV( y ← α·op(A)·x + β·y )
- A( m×n ), x( n ) → y( m )
- Level-3 (행렬-행렬): GEMM( C ← α·op(A)·op(B) + β·C )
- A( m×k ), B( k×n ) → C( m×n )
- GPU는 이게 최고 효율(연산/메모리 비율이 큼)
왜 이게 중요한가(모든 걸 GEMM/GEMV로 생각하기)
대부분의 ML/DL 핵심 연산은 결국 아래 둘의 조합
- 로지스틱/선형회귀
- 예측: z = X @ w → GEMV (X: n×d, w: d)
- 그라디언트: g = Xᵀ @ (p − y) → GEMV(전치)
- (선택) Xᵀ X → GEMM, Xᵀ y → GEMV
- Ridge/OLS (직접해법)
- XtX = Xᵀ X → GEMM, Xty = Xᵀ y → GEMV
- 선형시스템 (XtX + αI) w = Xty → 선형해법(Cholesky/QR/CG)
- KNN/KMeans (거리)
- ∥x − y∥2=∥x∥2+∥y∥2−2x⋅y\|x\!-\!y\|^2 = \|x\|^2 + \|y\|^2 − 2 x·y
- x·y 부분을 큰 GEMM으로 처리 + 노름은 벡터 리덕션
- 소프트맥스/시그모이드/손실: 원소별 연산(elementwise) + 리덕션(sum/mean)
→ 커널 하나(혹은 두세 개)면 충분
최소 연산 체크리스트(진짜 필요한 것)
“레이어별 커널 잔뜩”은 필요 없고, 아래만 있으면 대부분 커버돼.
- BLAS 기본
- GEMM, GEMV, DOT, AXPY, SCAL, 리덕션(sum, mean)
- (있으면 좋음) Strided-batched GEMM: 작은 행렬 다수 처리
- 원소 연산
- add_bias(행 단위), sigmoid, softmax(안정 버전), logsumexp, clip
- 선형시스템/최적화
- Cholesky/QR solve(cuSOLVER) 혹은 CG(Conjugate Gradient) 반복해법
- Prox-soft-threshold(L1용 shrink): Lasso/ElasticNet의 핵심
- (옵션) 거리/히스토그램
- KNN/KMeans용 pairwise 거리(사실상 GEMM 변형)
- 트리/GBDT는 히스토그램 축적(초기엔 CPU로 두자)
“Backend” 클래스를 두면 쉬워진다
레이어 중심이 아니라 연산 중심으로 한 층을 두면, 상위 알고리즘은 수학만 신경 쓰면 돼.
class Backend:
def gemm(self, A,B, tA=False, tB=False): ...
def gemv(self, A,x, tA=False): ...
def add_bias(self, X,b): ...
def sigmoid(self, Z): ...
def softmax(self, Z): ...
def sum(self, X, axis=None): ...
def cholesky_solve(self, A,b): ... # Ridge/OLS
def prox_soft_threshold(self, w,tau): ... # L1(엘라스틱넷)
- CPUBackend → numpy/scipy로 위 함수 구현
- CUDABackend → cuBLAS/cuSOLVER/네 커널로 구현
- 알고리즘(Linear/Logistic/Lasso 등)은 오직 backend.gemv/gemm/...만 호출
'dev_AI_framework' 카테고리의 다른 글
| CuPy 백엔드 방식과 직접 cuBLAS 래퍼 방식의 사용 (1) | 2025.08.29 |
|---|---|
| BACKEND 부분 수정하기... 연산 방식의 수정 (0) | 2025.08.28 |
| GPU 구현, CPU 구현 비교 (0) | 2025.08.28 |
| RNN 추가 - OpStruct 벡터 API 로 확장 + 레거시 호환ㅂ (3) | 2025.08.25 |
| optimizer — SGD / Momentum / Adam (CUDA) (0) | 2025.08.23 |