본문 바로가기

dev_AI_framework

RNN 추가 - OpStruct 벡터 API 로 확장 + 레거시 호환ㅂ

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로 전파.