1) 포인터 소유권/수명 모델 (ownership & lifetime)
- 파이썬 제공 포인터
- x, y, weights, bias 는 파이썬 쪽에서 할당된 디바이스 메모리 주소, (.data.ptr) 가 pybind 로 넘어옴
- 파이썬에서 참조를 유지해야 CuPy CG 가 메모리를 회수하지 않음, self.tensor_map[name] = cp_arr 같은 보관이 필수
- 프레임워크(런타임) 임시 버퍼
- run_graph_cuda() 가 중간 output 을 cudaMalloc 하여 새로 만든 디바이스 버퍼
- forward 종료 뒤 정리 대상
- 정리 규칙
- forward 시작 지점에 user_keys = set(tensor_ptrs.keys()) 스냅샷
- forward 끝난 뒤 for (auto& kv : tensors) if (kv.first not in user_keys and kv.first != pred_id ) cudaFree(kv.second);
- 위와 같이 하면 사용자 포인터/최종 출력만 남고, 나머지 임시 버퍼는 정리됨
2) ID와 버퍼의 불변식 (naming invariants)
- 각 연산은 (input_id, param_id, output_id)를 가짐. 이 문자열 ID가 키가 되어 tensors[id] -> float* 로 매핑됨.
- LOSS 노드의 입력이 바로 모델의 “예측” 텐서여야 함.
- BCE의 y_pred는 마지막 Activation(Sigmoid) 출력.
- 실수로 **Dense 선형 출력(로짓)**을 y_pred로 쓰면 음수/1초과가 들어가서 손실/기울기가 폭주하거나 0/16로 튐.
- 따라서 손실 계산부에서:
- if E.back().op_type == LOSS: pred_id = E.back().input_id else: pred_id = final_output_id
- 그리고 반드시 y_pred = tensors[pred_id] 를 사용.
3) 배치 포인터 오프셋 (per-batch pointer arithmetic)
- 내부 커널은 각 배치 샘플에 대해 input_b = base + b * (rows*cols) 형태로 오프셋을 더함.
- **shape의 rows/cols는 “한 샘플 크기”**로 유지하고, 실제 할당은 batch_size * rows * cols 바이트.
- forward/backward/손실 모두 동일한 규칙으로 오프셋을 계산해야 함.
- 어느 한 곳에서라도 “배치 차원 없는 길이”로 계산하면 엉뚱한 위치를 읽거나 씀.
4) 흔한 참조 실수와 증상
| BCE에 로짓을 y_pred로 전달 | 손실이 0 ↔ 16 근처로 튐, y_pred에서 음수/1초과 관찰 | 손실 계산 직전 주소 출력: [PTR] y_pred=…, act_out=…, dense_out=… → y_pred가 act_out과 동일해야 정상 |
| 임시 버퍼를 free하지 않음 | evaluate()나 긴 학습 중 멈춤/다운 | forward 종료 후 user_keys 외 버퍼 cudaFree |
| CuPy 배열이 GC로 해제됨 | 랜덤 크래시/멈춤/쓰레기 값 | 파이썬에 참조(딕셔너리)에 영구 보관 |
| BCE 경로에서 중복 평균 (예: backward가 /batch 했는데 어딘가에서 /size 추가) | 기울기 너무 작아서 학습 정체 | bce_loss_backward 외에 추가 나눗셈 전역 검색(/ size, / n, / batch 등) |
| 포인터 alias/in-place | 입력/출력이 같은 버퍼로 alias되면 덮어써서 오동작 | 각 op에서 input/output이 서로 다른 포인터인지 점검(의도적 in-place 아니면 금지) |
'dev_AI_framework' 카테고리의 다른 글
| 배치 루프 (여러 번 런치) vs 배치 결합 (한 번에 런치) (4) | 2025.08.15 |
|---|---|
| 연산 방식의 변경 - 임시 버퍼/전치 커널 , 커스텀 matmul backward 제거 (0) | 2025.08.15 |
| 문제 해결 완료, XOR 수렴 확인 야호~ (4) | 2025.08.11 |
| XOR test 의 출력 확인 (1) | 2025.08.09 |
| run_graph_backward의 각 변수 해석 (0) | 2025.08.09 |