완벽한 재현이 어려운 이유
현대 GPU 코드는 속도를 높이기 위해 비결정적 커널을 사용해. 병렬 축약 과정에서 연산 순서가 달라질 수 있고, atomic add는 비트 단위로 같은 결과를 보장하지 않아. cuDNN도 runtime에 가장 빠른 합성곱 알고리즘을 선택해. 그래서 시드를 고정해도 두 학습 결과가 몇 에폭 뒤부터 소수점 셋째 자리에서 달라질 수 있어.
보통 필요한 건 비트 단위 재현성이 아니라 통계적 재현성이야. 최종 정확도가 ± 0.1% 안에 들고 손실 곡선의 모양이 같으면 돼. 시드를 고정하고 데이터 순서를 일정하게 유지한 뒤 몇 가지 cuDNN 플래그를 설정하면 이 정도는 달성할 수 있어.
random, numpy, PyTorch CPU, PyTorch CUDA, DataLoader worker_init의 시드를 모두 고정해. 그래도 GPU의 비결정성 때문에 소수점 셋째 자리부터 결과가 달라질 수 있다는 점은 받아들여야 해.시드 설정 절차
학습 코드 맨 위에서 모델을 만들기 전에 set_seed(42)를 호출해. 비교할 실행에는 같은 시드를 사용해. Ablation에서는 한 번에 하나의 설정만 바꾸고 시드는 그대로 유지해.
비트 단위 결정성이 필요할 때
유닛 테스트, 회귀 테스트, 일부 규제 적용 파이프라인에서는 torch.use_deterministic_algorithms(True)를 설정하고 자주 2x에 이르는 속도 저하를 감수해야 해. 행렬곱의 결정성을 확보하려면 CUBLAS_WORKSPACE_CONFIG=:4096:8도 설정해. Python version, package version, GPU driver를 포함한 전체 실행 환경을 저장해야 해. 모든 플래그를 설정해도 환경이 조금만 달라지면 결정성이 깨질 수 있어.