1) OpStruct 벡터 API로 확장 + 레거시 호환
- op_structs.h
- inputs: vector<string>, params: vector<string> 추가.
- 레거시용 input_id, param_id 유지.
- normalize_legacy()로 레거시 → 벡터 자동 이관.
- 도우미
- resolve_A_id(op): inputs[0] → fallback input_id
- resolve_B_id(op): inputs[1] 또는 params[0] → fallback param_id
2) Forward 엔진(run_graph.cu)
- 진입 시 모든 노드를 정규화(legacy→vector) 후 스위치 분기.
- MATMUL: TF32 strided-batched GEMM 사용, Bias Fuse(다음 op이 ADD_BIAS/row-wise ADD면 합쳐서 실행).
- ADD / ADD_BIAS: row-wise(len=cols), col-wise(len=rows) 브로드캐스트 지원.
- Activations: 공용 launch_activation_forward(...) 호출 (ReLU/Sigmoid/Tanh/Leaky/ELU/GELU/SiLU).
- Softmax: 온도 파라미터 지원.
- Flatten: 요소 수 보존 검증 후 memcpy.
- Pooling(MAX/AVG): NCHW 메타를 extra_params로 전달, 아웃은 per-sample 2D 뷰 (C, Hout*Wout)로 shape 등록. Max는 argmax 작업공간 캐시(ensure_argmax_ws).
- Conv2D: NCHW 전용 커널 호출(앞/뒤 패스와 동일한 shape 식 사용).
- Time utils: SLICE_TIME, CONCAT_TIME CUDA 커널 추가. (동일 TU에 정의하여 링크 문제 제거)
3) Backward 엔진(run_graph_backward.cu)
- 진입 시 정규화(legacy→vector) 적용.
- LOSS:
- BCE/MSE/CCE 역전파 구현.
- 직전 op이 SOFTMAX이고 loss가 CCE면 fused softmax‑xent(∂L/∂z = (p−y)/B) 경로 사용.
- MATMUL:
- dX = dY·W^T(strided-batched)
- dW = Σ_b (X_b^T·dY_b) → 임시 (B,K,N) 후 배치축 합산.
- ADD/ADD_BIAS:
- dX = dY.
- 편향 grad: row-wise는 행 합(reduce over rows), col-wise는 열 합 → 배치축 합.
- Activations/Softmax: 공용 backward 커널.
- Flatten: grad 전달만.
- Conv2D: per‑sample rm 그라드를 NCHW로 패킹 → dX, dW 계산.
- Pooling: forward 저장된 argmax로 MaxPool bwd / AvgPool bwd.
4) Python 측(Sequential)
- compile()
- 레이어들의 to_e_matrix()로 얻은 E_raw/weights/biases/shapes를 수집.
- Loss 노드 추가(라벨 id="y_true"), loss_type 저장.
- E_raw → OpStruct[] 변환 시 벡터/레거시 모두 안전하도록 _to_opstruct() 사용.
- train_on_batch() / fit() / evaluate()
- 라벨 shape 등록: _ensure_label_shape() — output shape와 맞춤.
- Optimizer state(velocity/m,v) 버퍼 지연 할당.
- 엔트리포인트 호출(train_step_entry, run_graph_with_loss_entry, run_graph_forward_entry).
- 디버그 유틸
- grad dump/quick grad check에서 BWD 리턴 dict 우선 사용으로 수정.
RNN은 어떤 방식으로 추가했나
연산자 설계
- 새 OpType: RNN (기존 enum 뒤에 추가, 기존 값 보존)
- 입력/파라미터
- inputs[0] = X : [B,T,D] per-sample 2D view는 (T,D)
- params[0] = Wx : [D,H]
- params[1] = Wh : [H,H]
- params[2] = b : [H] 또는 [1,H] (선택)
- params[3] = h0 : [B,H] (선택)
- 레거시(input_id/param_id)도 허용되지만, 벡터 API 우선.
- 출력
- output_id: 기본 최종 은닉 H_T (per-sample (1,H)) 또는 Python에서 shape를 (T,H)로 주면 return sequences로 동작.
- 항상 output_id + "::__rnn_hseq"에 **전체 시퀀스 H_seq [B,T,H]**를 저장(역전파용 캐시).
메타/Shape 전달
- OpExtraParams에 힌트 필드:
- time_steps, hidden_size, input_w, output_c 등.
- 미지정 시 입력/shape에서 유추:
- T = in_shape.rows, D = in_shape.cols, H = extra.hidden_size or extra.output_c
- Python 레이어가 출력 shape를 명시하면 그대로 사용(예: (T,H) → return_seq=True).
Forward
- launch_rnn_forward_simple(...) 호출(커스텀 CUDA):
- tanh 기본(필요 시 Act 스위치 확장 가능).
- bias/h0 미지정 시 0 버퍼를 내부 캐시로 할당.
Backward
- launch_rnn_backward_simple(...):
- out이 (1,H)면 dH_T 경로, (T,H)면 dH_seq 경로.
- 출력: dX [B,T,D], dWx [D,H], dWh [H,H], db [H], dh0 [B,H]
- 선택 파라미터(Wh, b, h0)를 주지 않았다면 계산된 grad 버퍼를 해제(그라디언트 등록 안 함).
- gradients[A_id]에 dX를 등록해 이전 op로 전파.
'dev_AI_framework' 카테고리의 다른 글
| GPU 백엔드와 GEMM/GEMV 에 대해... (1) | 2025.08.28 |
|---|---|
| GPU 구현, CPU 구현 비교 (0) | 2025.08.28 |
| optimizer — SGD / Momentum / Adam (CUDA) (0) | 2025.08.23 |
| cnn — Conv2D CUDA Kernels (NCHW) (0) | 2025.08.23 |
| bias — Row/Col-wise Bias Add Kernels (0) | 2025.08.23 |