~/우성현

← 모든 프로젝트

torch.compile 정합성 퍼저 + PyTorch 수정 PR

별칭·뷰·in-place 연산에 특화한 차등 퍼저로 torch.compile이 오류 없이 틀린 값을 내는 버그를 찾아, PyTorch에 보고하고 수정 PR을 올렸습니다

기간
2026.09
역할
1인 개발 · AI 코딩 에이전트 협업
저장소
wwoosshh/AI-accelerator-compiler
스택
  • Python
  • PyTorch
  • torch.compile
  • Dynamo
  • AOTAutograd
  • Inductor
  • Triton
  • C++

핵심 수치

2026-09-29 기준 · 기여·릴리스 수치는 매일 자동 갱신

문제

torch.compile은 파이썬으로 쓴 PyTorch 코드를 그래프로 바꿔 최적화합니다. 이 과정에서 같은 메모리를 가리키는 텐서(별칭), 뷰, in-place 변경이 섞이면, 컴파일된 코드가 오류 없이 eager 실행과 다른 값을 내는 경우가 있습니다. 이런 “조용한 오답”은 오류가 나지 않으므로 결과가 틀려도 알아차리기 어렵습니다.

접근

  • 별칭·뷰·in-place 연산 조합에 집중한 작은 프로그램 생성기와 차등 오라클(aliasfuzz)을 만들었습니다.
  • 반환값만 비교하지 않고, 입력 텐서의 최종 상태, 별칭 관계, 파이썬 부작용까지 eager 실행과 비교합니다.
  • 정수 값을 써서 허용오차 0으로 비교하고, 정의되지 않은 동작은 생성 단계에서 뺐습니다.
  • 퍼저를 Dynamo만(eager), AOTAutograd(aot_eager), Inductor(Triton) 세 계층에 각각 돌리고, 재현 코드는 백엔드를 바꿔 가며 어느 단계에서 틀어지는지 좁혔습니다.

결과

  • torch 2.14.0에서 약 21,000개 프로그램(45분)을 돌려, 나이틀리에서도 재현되는 새로운 조용한 오답 7계열을 찾았습니다.
  • 원인을 코드 위치까지 규명해 PyTorch에 이슈 6건(조용한 오답 5건, 크래시 1건)을 올렸습니다. 7계열 중 6계열이 이슈 4건에 대응하고(H1~H3은 #198094 한 건으로 묶었습니다) G는 아직 보고하지 않았습니다. 나머지 이슈 2건은 7계열에 들지 않는 크래시 F(#198100)와 NNSmith 비교에서 나온 L(#198131)입니다.
  • 이슈마다 수정 PR을 올렸고(6건), 모두 회귀 테스트를 넣었습니다. 메인테이너가 남긴 리뷰와 리뷰어가 요청한 자동 리뷰에는 수정 커밋으로 대응했고, 1건은 이슈에서 먼저 논의하라는 절차 안내를 받았습니다.

주요 결정

  • 같은 20분 예산으로 기존 퍼저 NNSmith와 동시에 돌려 비교했습니다. NNSmith가 보고한 불일치 34건은 재검증해 분류한 결과 모두 부동소수점 수치 차이였고, aliasfuzz는 값이 달라지는 조용한 오답 30건(서로 다른 원인 6계열)을 찾았습니다. NNSmith는 별칭·in-place를 쓰지 않는 함수형 그래프를 탐색하는 도구라 이런 계열이 나오지 않는 것은 설계상 당연하고, 이 실험은 그 공간을 탐색하는 도구가 없으면 이 6계열은 발견되지 않는다는 점을 보여줍니다.
  • 오라클은 반환값뿐 아니라 입력의 최종 상태와 별칭 관계까지 비교하도록 설계했습니다. 오라클 절제 분석에서 반환값 비교만으로는 발견된 불일치 사례 151건 중 46건(약 30%)을 놓쳤습니다.

한계와 다음 단계

  • 수정 PR의 병합·리뷰 상태와 이슈의 분류 상태는 계속 바뀝니다. 현재 상태는 포트폴리오 사이트의 외부 기여 목록이 매일 자동으로 갱신합니다.
  • 7계열 중 동적 형상에서 별칭의 stride가 어긋나는 1계열(G)은 원인은 확정했지만 설계 결정이 필요해 아직 PyTorch에 보고하지 않았습니다.
  • unfold 수정 PR은 C++ 변경이라 Windows PC에서 컴파일하지 못한 채 올렸습니다.
  • 개인 Windows PC(RTX 4070 Ti)에서만 돌렸습니다. Inductor는 CUDA 백엔드만 검사했고, MSVC가 없어 CPU 백엔드는 검사하지 못했습니다.

AI 협업 방식

방향과 판단은 직접 했고, 구현과 문서 작업은 AI 코딩 에이전트(Claude Code)와 함께 했습니다. 이 저장소의 커밋 14개 중 10개에 Claude 공동 작성 표기가 있습니다. PyTorch에 올린 PR의 커밋에는 CLA 검사(EasyCLA)가 이 표기 때문에 실패해서 표기를 넣지 않았습니다.

외부 PR · 이슈

매일 자동 확인 · 마지막 변경 2026-10-07

  • 분류됨이슈 pytorch#198094 이슈

    [inductor] Scatter result reinplaced into a graph input that a later, unrelated mutation overwrites: y = slice_scatter(x, src); x.zero_(); return y returns zeros

  • 분류됨이슈 pytorch#198095 이슈

    [aot_autograd] Output that is a view of an aliased input (synthetic base) is regenerated from the wrong tensor: ta[0] returns t0[0], ta.view(-1) asserts on ViewMeta shape

  • 리뷰 중PR pytorch#198096 PR

    [inductor] Do not reinplace into a graph input that a later, unrelated mutation overwrites

  • 변경 요청PR pytorch#198097 PR

    [aot_autograd] Regenerate output aliases of merged (synthetic-base) inputs from metadata

  • 분류됨이슈 pytorch#198100 이슈

    [dynamo] x.contiguous().unsqueeze_(d) / x.to(x.dtype).unsqueeze_(d) crashes guard creation with IndexError: list index out of range (in-place view through a no-op alias of the input)

  • 해결됨이슈 pytorch#198101 이슈

    [inductor] Consumer of a dtype view of an input is computed after a later in-place mutation of that input (y = x.view(int32) * 2; y.sub_(-4); x[:, 2:5] = 2; return y.view(int64))

  • 분류됨이슈 pytorch#198102 이슈

    [functionalization] In-place mutation through a gapped unfold view (step > size) silently zeroes every base element not covered by a window under torch.compile

  • 리뷰 중PR pytorch#198103 PR

    [dynamo] Graph break on an in-place view of a no-op alias of a graph input

  • 병합됨PR pytorch#198104 PR

    [inductor] Realize consumers of aliasing buffers before a mutation of the aliased buffer

  • 닫힘 · 이슈에서 먼저 논의하라는 절차 안내PR pytorch#198105 PR

    [functionalization] unfold inverse: keep base elements that no window covers

  • 해결됨이슈 pytorch#198131 이슈

    [inductor] `dst[:] = src[:]; src.add_(1)` copies the *updated* `src` into `dst` (remove_noop_ops replaces a copy of an input by the input itself, which is mutated before the copy's user runs)

  • 병합됨PR pytorch#198132 PR

    [inductor] remove_noop_ops: keep a copy of an input that is mutated before the copy's user runs