
"어제랑 결과가 왜 다르죠?" 모델 재현성 악몽을 끝낼 RepDL 이야기
모델 재현성 문제를 해결하기 위해 마이크로소프트가 공개한 RepDL 라이브러리를 소개합니다. 비트 단위까지 일치하는 결정론적 연산의 중요성과 활용 방안을 다룹니다.
김영태
테크리드

안녕하세요. 풀링포레스트 테크리드 김영태입니다.
얼마 전, 입사한 지 얼마 안 된 주니어 ML 엔지니어 한 분이 사색이 되어 저를 찾아왔습니다. 로컬 개발 환경(A100 GPU)에서는 정확도가 98% 나오던 모델이, 스테이징 서버(T4 GPU)에만 올라가면 미세하게 결과가 틀어진다는 것이었습니다. 시드(Seed)값도 고정했고, 코드도 토씨 하나 안 틀리고 똑같은데 말이죠. 인프라를 담당하는 입장에서 이런 문의를 받으면 등줄기에 식은땀이 흐릅니다. "서버 환경 설정이 잘못됐나?" 하는 의심부터 들기 때문입니다.
솔직히 말해, 이런 '비결정론적(Nondeterministic)' 문제는 딥러닝 인프라를 다루는 개발자들에게는 오랜 골칫거리였습니다. 우리는 흔히 컴퓨터가 수학을 완벽하게 계산할 것이라 믿지만, 부동소수점(Floating Point)의 세계는 그렇게 호락호락하지 않습니다. GPU 아키텍처가 달라지거나, 병렬 연산의 순서가 미세하게 바뀌기만 해도 최종 결과값의 비트(Bit) 단위가 달라질 수 있습니다.
이 문제를 해결하기 위해 보통 파이토치(PyTorch)에서 torch.use_deterministic_algorithms(True) 같은 옵션을 켜곤 합니다. 하지만 뼈저리게 느낀 건, 이것만으로는 부족하다는 사실입니다. torch.mm이나 torch.div 같은 아주 기본적인 연산조차 하드웨어에 따라 결과가 달라질 수 있거든요.
막막해하던 차에, 마이크로소프트에서 흥미로운 오픈소스 프로젝트를 공개했습니다. 바로 RepDL(Reproducible Deep Learning)입니다.
이 라이브러리의 핵심 컨셉은 명확합니다. "어떤 하드웨어를 쓰든 비트 단위(Bit-level)로 완벽하게 동일한 결과를 보장한다"는 것입니다. 단순히 랜덤 시드를 고정하는 수준을 넘어서, 연산 자체의 순서와 방식을 강제하여 재현성을 확보하는 방식입니다.
사용법은 생각보다 간단해서 놀랐습니다. 기존 파이토치 모델을 래핑하기만 하면 됩니다.
import repdl
# 기존 모델을 RepDL 호환 모델로 변환
model = repdl.from_torch_module(original_model)이렇게 하면 내부적으로 repdl.ops에 정의된 연산들을 사용하게 됩니다. 예를 들어, 하드웨어 특성을 많이 타는 행렬 곱셈이나 나눗셈 같은 연산들이 RepDL이 제공하는 결정론적(Deterministic) 함수로 대체되는 것이죠.
실제로 저장소에 있는 예제를 살펴보면, examples/mnist_training.py를 실행했을 때 초기 모델의 해시값부터 학습된 모델의 해시값, 그리고 최종 테스트 정확도(0.9804)와 로짓(Logits)의 해시값까지 완벽하게 일치하는 것을 볼 수 있습니다. 우리가 겪었던 그 '미세한 오차'를 원천 차단하는 셈입니다.
물론, "공짜 점심은 없다"는 엔지니어링의 불문율은 여기서도 적용될 겁니다. 연산 순서를 강제하고 IEEE-754 표준을 엄격하게 준수하도록 강제한다는 것은, 필연적으로 연산 속도 최적화(Optimization)를 일부 포기해야 한다는 뜻일 수 있습니다. 학습 속도가 얼마나 느려질지, 리소스를 얼마나 더 먹을지는 실제 벤치마크를 돌려봐야 알 수 있겠죠.
하지만 금융권이나 의료 데이터처럼 0.0001%의 오차도 허용하기 힘든 민감한 도메인, 혹은 저희 풀링포레스트처럼 다양한 고객사 환경(온프레미스, 클라우드 등)에 모델을 배포해야 하는 입장에서는 '속도'보다 '신뢰성'이 중요할 때가 있습니다. 디버깅할 때 "하드웨어 차이인가?"라는 변수를 지울 수 있다는 것만으로도 엄청난 안도감을 주니까요.
현재 이 프로젝트는 연구 목적(Research Project)으로 공개되었고, 아직 모든 파이토치 함수를 지원하지는 않습니다. repdl/ops.py나 backend 폴더를 보면 직접 C++/CUDA 구현체를 바인딩해서 쓰고 있는데, 필요한 연산이 없다면 직접 기여(Contribute)를 해야 할 수도 있습니다. 프로덕션에 당장 적용하기엔 이르지만, 테스트 환경에서 모델 정합성을 검증하는 용도로는 충분히 가치가 있어 보입니다.
인프라의 복잡도가 올라갈수록, 기본을 지키는 도구들이 절실해집니다. 어제 돌린 모델이 오늘 결과가 다르다면, 혹은 내 로컬과 동료의 로컬 결과가 다르다면, 코드를 의심하기 전에 RepDL 같은 도구를 한번 살펴보시는 건 어떨까요? 적어도 "컴퓨터가 이상해요"라는 막연한 공포에서는 벗어날 수 있을 겁니다.


