1) GEMM 출력 레이아웃을 잘못 가정
- 증상: 임의 W/B에서 forward 오차 큼. W=0(=bias만) 또는 one-hot(W[0,0,0,0]=1)일 때만 맞음.
- 원인: A @ W 결과를 **[HWo, Cout]**로 만들고도, 최종 출력 버퍼 y_n(NCHW 연속)을 **[HWo, Cout]**처럼 써버림.
NCHW에서는 한 배치의 y_n 메모리가 [Cout, HWo] (채널이 행, HWo가 연속) 이어야 한다. - 해결: GEMM은 임시 Y_tmp[HWo, Cout]에 뽑고 → transpose 해서 y_n[Cout, HWo]에 기록.
2) W 패킹 시 K축 전개 순서(kh/kw) 뒤바뀜
- 증상: bias만/one-hot은 통과하지만, 랜덤 W에서만 크게 틀림.
- 원인: im2col이 K를 (ci, kh, kw)(그리고 kw가 최속)로 전개하는데, W pack 커널이 **(ci, kw, kh)**로 해석(=kh/kw 스왑).
- 해결: W pack/unpack 커널 전부 kw → kh → ci 순서(= kw fastest)로 통일.
3) GEMM bias 브로드캐스트 축이 틀림
- 증상: W=0, B≠0에서 오차(혹은 반대).
- 원인: gemm_run의 bias를 열(column) 기준으로 더한다는 가정으로 넣었는데, 실제 최종 출력 버퍼는 **[Cout, HWo]**여서 행(row=채널) 기준으로 더해야 맞음.
- 해결: gemm_run의 bias 사용 비활성화하고, 최종 y_n[Cout, HWo]에 대해 **row-wise(채널 축)**로 직접 더하는 커널(add_bias_rows) 사용.
4) Backward에서 dY 레이아웃 오해
- 증상: numeric grad에서 dW, dB 불일치.
- 원인: forward에서 최종 Y를 [Cout, HWo]로 저장했는데, backward에서 dY를 **[HWo, Cout]**인 것처럼 처리:
- dB: reduce_db가 [HWo, Cout] 가정 → 채널 합산 축 잘못.
- dW: dY에 불필요한 transpose 적용.
- dX: 전치 없이 [HWo,Cout]로 가정하고 곱함.
- 해결:
- dB: dY[Cout, HWo]를 HWo로 합산(row-wise reduce).
- dW: dY[Cout, HWo] @ X_col[HWo,K]로 그대로 곱함(전치 제거).
- dX: transpose(dY) → [HWo, Cout] 만든 뒤 @ W_CK 수행.
한 줄 요약
- 행렬 곱: 출력/그라디언트 텐서를 **실제 메모리 레이아웃([Cout, HWo])**에 맞추지 않고 [HWo, Cout]로 취급한 게 근본 원인.
- bias: 채널(row) 축으로 브로드캐스트해야 하는데 열(column) 축처럼 더한 게 문제.
- W pack: im2col의 K 전개 순서와 불일치(kh/kw 뒤바뀜).
- Backward: dY의 레이아웃 해석 오류로 dB/dW/dX 축 처리 전부 어긋남.
'dev_AI_framework' 카테고리의 다른 글
| 어느 단위 레벨까지 구현해야 할까 에 대한 고민 - 기본 레벨 연산들은 끝도 없 (0) | 2025.09.24 |
|---|---|
| CUDA Backend: Slice & Concat 연산 문서 (0) | 2025.09.24 |
| Conv2D (NCHW, group=1) 구현/연산 (0) | 2025.09.23 |
| LLM 과 접목, 최적화 커널 구성과 빌드, 모듈 생성의 과정을 자동화 (0) | 2025.09.23 |
| 특정 모델 구조/레이어 집합을 커널 최적화된 CUDA 코드 생성 시스템 (0) | 2025.09.23 |