1) 개요
- 입력 텐서 X:[M,N] (f32, RowMajor, CUDA)에 대해 학습 시 무작위로 일부 요소를 0으로 드랍하고, 필요 시 학습 시 스케일을 적용합니다.
- 선택적으로 마스크 텐서를 생성·반환하여 역전파에서 재사용합니다.
- 역전파는 dY와 mask를 받아 dX를 계산합니다.
2) 인터페이스 (C++)
2.1 Attributes
struct DropoutAttrs {
float p{0.5f}; // 드랍 확률 ∈ [0,1)
bool scale_in_train{true}; // 학습 시 1/(1-p) 스케일 적용 여부
uint64_t seed{0}; // RNG 시드 (0: 구현이 내부 시드/카운터 사용 가능)
};
- scale_in_train = true:
- Forward: Y = (mask ⊙ X) * (1/(1-p))
- Backward: dX = (mask ⊙ dY) * (1/(1-p))
- scale_in_train = false:
- Forward: Y = mask ⊙ X
- Backward: dX = mask ⊙ dY
2.2 런타임 API (backend CUDA)
Status DropoutCudaLaunch(
const Tensor& X,
Tensor& Y,
Tensor* mask, // optional (nullptr 허용), I32 [M,N]
const DropoutAttrs& attrs,
StreamHandle stream);
Status DropoutCudaBackwardLaunch(
const Tensor& dY,
const Tensor& mask, // I32 [M,N]
Tensor& dX,
const DropoutAttrs& attrs,
StreamHandle stream);
Tensor 요구사항
- 공통: device == CUDA, layout == RowMajor, shape는 2D.
- X, Y, dY, dX: DType::F32, shape 일치.
- mask: DType::I32, shape가 입력과 동일. 생성/사용 모두 2D int32.
2.3 얇은 엔트리 (ops)
int dropout_run(const Tensor& X, Tensor& Y, Tensor* mask,
const ai::DropoutAttrs& attrs, StreamHandle stream);
int dropout_backward_run(const Tensor& dY, const Tensor& mask, Tensor& dX,
const ai::DropoutAttrs& attrs, StreamHandle stream);
- 입력 검증 후 DropoutCudaLaunch / DropoutCudaBackwardLaunch 위임.
- 성공 시 0, 실패 시 음수 에러 코드(-2 형식/장치/레이아웃/차원 문제, -3 shape mismatch, -7 런타임 오류 등).
3) 커널 구조
3.1 커널 런처 (kernels.cu)
void dropout_forward_kernel_launcher(const float* X, float* Y, int32_t* mask,
int M_rows, int N_cols,
float p, bool scale_in_train,
uint64_t seed, cudaStream_t s);
void dropout_backward_kernel_launcher(const float* dY, const int32_t* mask, float* dX,
int M_rows, int N_cols,
float p, bool scale_in_train,
cudaStream_t s);
- 이름 충돌 방지를 위해 포인터 마스크는 mask, 행/열은 M_rows, N_cols로 통일.
- 내부 스케일:
scale = scale_in_train ? ((p < 1.f) ? 1.f/(1.f-p) : 0.f) : 1.f
3.2 Forward 커널 요약
- 그리드: grid(M_rows), 블록: block(256)
- 각 행(row)을 블록이 담당하고, 열 방향으로 stride loop.
- 난수 생성: (seed ^ (row * LARGE_PRIME + col)) 형태 등으로 간단히 독립 난수 생성 (구현에 따라 Philox/XORWOW 대체 가능)
- mask[i] = (rand >= p) ? 1 : 0
- Y[i] = X[i] * mask[i] * scale
- mask 포인터가 nullptr인 경우, 내부적으로 드랍을 수행하지만 마스크 기록을 생략(옵션). (권장: 역전파가 필요하면 반드시 마스크를 제공)
3.3 Backward 커널 요약
- 입력: dY, mask
- dX[i] = dY[i] * mask[i] * scale
- scale는 Forward와 동일 규칙(학습 시 스케일 on/off)에 맞춤.
4) PyBind 바인딩 (요약)
- Python에서 호출될 때는 내부적으로 TensorDesc를 생성하여 CUDA 메모리를 wrap하고, 위 얇은 엔트리를 통해 호출.
- 테스트 용도 API (예):
- ge.dropout(X, p=0.5, seed=123, return_mask=True) → (Y, mask)
- ge.dropout_backward(dY, mask, p=0.5) → dX
(바인딩 함수명/시그니처는 프로젝트 내 py_api.cpp 정의에 따릅니다.)
5) 에러 처리/검증
- 형식/장치/레이아웃 체크:
- F32(입출력), I32(mask), 2D RowMajor, CUDA device
- Shape 일치:
- X, Y 동일 shape
- mask 존재 시 X와 동일 shape
- 역전파: dY, dX, mask shape 동일
- CUDA 런치 오류:
- cudaPeekAtLastError()로 확인하여 Status::RuntimeError로 전파
- 에지 케이스:
- p == 0 → mask ≡ 1, Y == X (scale=1 또는 1/(1-0)=1)
- p → 1 → 모두 드랍(수치적으로 1은 금지). scale_in_train && p==1일 때 scale=0으로 정의해 overflow 회피.
6) 결정성(Determinism) & 시드
- seed를 지정하면 동일 입력/시드/스트림에서 반복 실행 시 동일 마스크를 생성(커널 내 per-element 시드 조합 방식).
- 멀티-스트림/멀티-런치 환경에서 완전 결정성을 보장하려면 고정된 seed + 일관된 launch partitioning을 유지해야 합니다.
- 더 강한 결정성이 필요하면 Philox 기반 카운터 RNG로 전환 권장(현재는 간단한 per-element 혼합 시드).
7) 성능 메모
- 256 thread/block 설정 (행당 1블록). 일반적 [M,N]에서 메모리 대역/분기 예측친화적.
- 마스크는 int32로 저장(원자 연산 없음). 필요 시 uint8/bit-pack 최적화 가능.
- 스케일은 커널 외부에서 상수 계산 후 인자로 전달 → 불필요한 분기 제거.
8) 사용 예시 (NumPy 기준)
import numpy as np
from graph_executor_v2 import _core as ge
M, N = 8, 16
X = np.random.randn(M, N).astype(np.float32)
# Forward (마스크 반환)
Y, mask = ge.dropout(X, p=0.3, seed=42, return_mask=True)
# Backward
dY = np.random.randn(M, N).astype(np.float32)
dX = ge.dropout_backward(dY, mask, p=0.3)
- scale_in_train=True가 기본이므로 학습 시 통상적인 기대값 보존(E[Y]=X)이 됩니다.
9) 테스트 요약
- 정상성: p=0 → Y==X, dX==dY
- 스케일: scale_in_train=True일 때 드랍 후 평균 스케일링 검증
- 결정성: 동일 시드 반복 호출 시 마스크 동일
- 역전파: dX = mask ⊙ dY * scale 검증
10) 소스 트리 포인터
- backends/cuda/ops/dropout/kernels.cu
- dropout_fwd_kernel, dropout_bwd_kernel + 런처
- backends/cuda/ops/dropout/launcher.cu
- DropoutCudaLaunch, DropoutCudaBackwardLaunch
- src/ops/dropout.cpp
- ai::ops::dropout_run, ai::ops::dropout_backward_run
- src/bindings/py_api.cpp
- Python 바인딩 함수 (테스트 진입점)
'dev_AI_framework' 카테고리의 다른 글
| 특정 모델 구조/레이어 집합을 커널 최적화된 CUDA 코드 생성 시스템 (0) | 2025.09.23 |
|---|---|
| Scaled Dot-Product Attention (SDPA) (0) | 2025.09.23 |
| Cross-Entropy 모듈 추가 / 수정 (0) | 2025.09.22 |
| Cross-Entropy (CUDA) (0) | 2025.09.22 |
| Softmax Operation — Design & Implementation Notes (0) | 2025.09.22 |