PyTorch 2.14 출시: NVGEMM 백엔드와 c10d 내결함성, Python 3.15 휠 지원 (feat. torchvision 0.29)

PyTorch 2.14 소개

PyTorch Foundation이 2026년 9월 2일 PyTorch 2.14를 공식 출시했습니다. 이전 버전인 PyTorch 2.13 이후 487명의 기여자가 2,995개의 커밋을 반영한 결과물로, 2026년부터 적용된 2개월 릴리즈 주기의 네 번째 결과물입니다.

이번 릴리즈를 이해하는 가장 빠른 방법은 2.13이 심어 둔 실험적 기능 세 가지가 각각 어디까지 자랐는지를 보는 것입니다. 2.13에서 Inductor에 두 번째 코드 경로로 붙었던 CuTeDSL 백엔드 는 에필로그 융합(epilogue fusion)과 저정밀도 GEMM까지 다루는 NVGEMM 이라는 이름의 본격적인 행렬 곱 백엔드가 되었고, 별도 저장소에서 실험되던 통신 라이브러리 torchcommsnccl2라는 이름으로 PyTorch 본체(in-tree)에 들어왔습니다. Apple Silicon은 2.13에서 어텐션 커널(FlexAttention)을 받았는데, 이번에는 SVD와 고윳값 분해를 포함한 선형대수(linear algebra) 전반이 네이티브 Metal 커널로 내려왔습니다.

여기에 이번 릴리즈만의 새로운 축이 하나 더 있습니다. 내결함성(fault tolerance)이 특정 백엔드의 구현 세부사항에서 c10d의 일급(first-class) 개념으로 승격 된 것입니다. 그동안 대규모 학습에서 랭크(rank) 하나가 죽으면 프로세스 그룹을 통째로 내리고 다시 띄우는 것이 표준 복구 절차였고, 클러스터 전체의 워밍업된 상태가 함께 버려졌습니다. 2.14는 프로세스 그룹을 그 자리에서 재구성하는 인터페이스, 상대의 참여 없이 원격 메모리를 읽고 쓰는 단방향 윈도우, 그리고 NCCL 전용이었던 Flight Recorder를 모든 백엔드에서 쓸 수 있게 만든 훅을 함께 제공합니다.

한 가지 더, 이번 릴리즈에는 사용자가 설치 방식을 다시 생각해 봐야 할 변화가 있습니다. 함께 출시된 torchvision 0.29.0이 torch 2.14에 대해 ABI(Application Binary Interface) 안정성을 확보하면서, 앞으로 torch를 올릴 때마다 torchvision을 같이 올려야 하는 관행이 사라집니다. 도메인 라이브러리가 PyTorch 본체와 같은 박자로 릴리즈되던 구조 자체가 바뀌기 시작한 것입니다.

한눈에 보는 8가지 변화

PyTorch 팀이 릴리즈 노트 맨 앞에 배치한 하이라이트는 다음 8가지입니다.

  • NVGEMM이 CuTeDSL로 생성한 CUTLASS 커널을 Inductor에 제공 합니다. 에필로그 융합, 스케일링된(scaled) GEMM과 NVFP4 GEMM, 그룹 리덕션(grouped-reduction) 에필로그가 Triton, ATen과 나란히 자동 튜닝(autotuning) 후보로 경쟁합니다.

  • PyTorch Distributed에 새 nccl2 백엔드가 추가 되었습니다. torchcomms에서 이식되었고, 논블로킹(nonblocking) 커뮤니케이터와 즉시(eager) 커뮤니케이터 분할을 포함한 집합 통신(collective) 계약 전체를 구현합니다.

  • 내결함성이 c10d의 일급 개념이 되었습니다. 프로세스 그룹의 인플레이스(in-place) 재구성, 단방향 원격 메모리 접근(Remote Memory Access, RMA) 윈도우, 그리고 NCCL만이 아니라 모든 백엔드에서 동작하는 Flight Recorder가 함께 들어왔습니다.

  • Apple Silicon이 네이티브 선형대수를 갖게 되었습니다. 야코비(Jacobi) 커널 기반 특이값 분해(Singular Value Decomposition, SVD), eigh, QR, 콜레스키(Cholesky) 분해가 추가되었고, 리덕션(reduction) 다섯 부분 재작성과 MPSGraph에서 Metal 커널로의 추가 이관이 함께 이뤄졌습니다.

  • torch.switchtorch.cond를 다분기(multi-way branching)로 일반화 하고, torch.while_loop을 CUDA 그래프 안에서 캡처할 수 있게 되었습니다.

  • @dynamic_spec으로 동적 shape를 선언적으로 지정 할 수 있고, 이 명세를 torch.compile, torch.export, make_fx가 함께 사용합니다.

  • 플랫폼 지원이 넓어졌습니다. ROCm 7.14 휠이 TheRock pip SDK에서 생성되고, Intel XPU가 네이티브 그래프 캡처를 추가했으며, Inductor가 NVIDIA의 차세대 아키텍처인 Rubin(sm_107)을 타깃합니다.

  • 복소수(complex-valued) 텐서에 대한 실험적 torch.compile 지원 이 추가되었습니다. 옵트인(opt-in) 방식으로, 지원되는 복소수 연산을 실수부와 허수부 계산으로 분해해 컴파일러 백엔드가 최적화할 수 있게 합니다.

NVGEMM: CUTLASS 커널이 에필로그까지 삼키다

행렬 곱(GEMM) 뒤에는 거의 항상 다른 연산이 이어집니다. 편향(bias) 덧셈, 활성화 함수, 스케일 재조정 같은 것들입니다. 2.13의 CuTeDSL 백엔드는 GEMM 커널 하나를 독립적으로 생성할 수 있었지만, 그 뒤에 붙는 연산은 별도 커널로 남아 결과 행렬을 메모리에서 다시 읽어야 했습니다. 대역폭이 병목인 워크로드에서는 이 재읽기가 그대로 손실입니다.

2.14의 NVGEMM은 NVIDIA의 공식 cutlass.operators API를 사용해 mm, addmm, scaled_mm에 대한 후보 커널을 생성하고, Triton 템플릿이 하던 것처럼 에필로그를 융합합니다. addmm의 편향 덧셈, 연쇄된 원소별(pointwise) 연산, GEMM 결과에 대한 리덕션이 모두 커널 안으로 들어가며, 리덕션 값과 전체 출력 행렬을 동시에 반환하는 경우까지 다룹니다. 저정밀도 경로에도 융합이 닿아서, 스케일링된 GEMM 뒤의 원소별 연산이 커널 안으로 접히고 NVFP4의 런타임 전역 스케일이 별도 곱셈이 아니라 에필로그 안에서 적용됩니다. 융합된 커널은 디스크에 캐시되므로 재컴파일 때 다시 만들지 않습니다.

사용하려면 max_autotune 아래의 max_autotune_gemm_backendsNVGEMM을 추가하면 됩니다. nvidia-cutlass-dsl 4.6.0이 필요하고, NVFP4 경로는 Blackwell 아키텍처를 요구합니다. 백엔드가 표현할 수 없는 에필로그는 Triton으로 폴백하므로 기존 융합이 깨지지는 않습니다. PyTorch 팀은 자동 튜닝 시간과 성능을 계속 개선하고 있다고 밝혔습니다.

같은 CUDA 진영에서 그룹 GEMM(grouped GEMM) 쪽 변화도 함께 봐야 합니다. 전문가 혼합(Mixture-of-Experts, MoE) 레이어는 서로 다른 모양의 행렬 곱 여러 개를 한 번에 발행하는데, 여기에 cuBLASLt가 CUTLASS와 폴백에 이어 세 번째 백엔드로 합류했습니다. 원문에 따르면 CUDA 13.2 이상의 Blackwell과 CUDA 13.3 이상의 Hopper에서 fp16은 기본값이고, 같은 조합의 bf16은 torch.backends.cuda.matmul.prefer_cublaslt_grouped_gemm = True로 옵트인합니다. 이 구분은 측정 결과를 반영한 것으로, 크기가 들쭉날쭉한 MoE 스타일 그룹에서는 이기지만 균일한 그룹에서는 대체로 CUTLASS bf16 커널에 뒤집니다. 사용자가 직접 챙겨야 하는 조건은 행렬과 leading dimension의 16바이트 정렬입니다.

분산 학습: 내결함성이 백엔드 세부사항에서 벗어나다

nccl2 백엔드와 이름 정리

2.13에서 torchcomms는 PyTorch Distributed의 CI와 디바이스 메시(device mesh) 경로에 통합된 별도 통신 백엔드였습니다. 2.14에서는 그 API가 본체로 들어와 USE_C10D_NCCL 빌드 플래그 뒤에서 nccl2 c10d 백엔드가 되었고, 재사용 가능한 NcclApi 추상화 위에 Work 계약 전체를 구현합니다. 이 백엔드는 즉시 실행(eager) 전용이며, 단방향 윈도우, 내결함성, 메모리 오프로드를 이용한 일시 중단과 재개 같은 새 기능을 함께 제공합니다.

이름이 여러 개로 늘어난 만큼 정리해 두면 좋습니다. 기존의 지연 초기화(lazy initialization) 동작이 필요한 워크로드에는 상대별 P2P 커뮤니케이터를 필요할 때 만드는 nccl-lazy 호환 래퍼가 있고, 기존 구현을 명시적으로 고르려면 nccl-legacy 백엔드를 쓸 수 있습니다. 반대로 nccl이라는 이름 뒤의 구현을 실험적인 새 것으로 바꾸려면 TORCH_DIST_USE_NCCL2=1 환경변수로 옵트인합니다.

프로세스 그룹을 그 자리에서 다시 만들기

랭크 하나가 죽었을 때 프로세스 그룹을 내리고 다시 띄우는 관행의 진짜 비용은 재시작 시간이 아니라 클러스터 전체에서 버려지는 상태입니다. 2.14는 BackendProcessGroup에 재구성(reconfiguration) 인터페이스를 노출해 그룹을 그 자리에서 다시 만들 수 있게 하고, 중단(abort) 훅과 집합 통신 전후 훅을 같은 경로로 연결했습니다. 내결함성 지원은 nccl2뿐 아니라 Gloo 백엔드에도 들어갔고, 재구성 API에 대한 문서가 함께 정리되었습니다.

이 흐름과 짝을 이루는 것이 단방향(one-sided) RMA 윈도우 API입니다. 기존의 양방향 집합 통신은 데이터를 주는 쪽과 받는 쪽이 짝이 맞는 호출을 서로 발행해야 하는데, BackendProcessGroup에 추가된 윈도우 인터페이스는 상대가 대응 호출을 하지 않아도 상대 메모리를 읽고 쓸 수 있게 합니다. 임베딩 조회, 가중치 전송, 전문가 라우팅처럼 접근 패턴이 불규칙한 작업에 맞는 방식이고, nccl2 백엔드를 통해 ncclGetncclPut API가 노출됩니다.

어떤 백엔드에서도 동작하는 Flight Recorder

Flight Recorder는 집합 통신 호출 이력을 담아 두는 버퍼로, 학습 잡이 멈추거나 랭크별 집합 통신이 어긋났을 때 원인을 찾는 데 쓰입니다. 문제는 이 도구가 NCCL에 묶여 있었다는 것이었습니다. 이제 FlightRecorderHookProcessGroup 훅을 통해 기록하므로 어떤 백엔드에서도 동작하고, 로그 직렬화도 DebugMode를 통해 이식 가능해졌습니다. DebugMode.save_logs()DebugMode.load_logs()로 JSON 직렬화가 가능하므로, 별개의 프로세스나 서로 다른 모델 구성에서 수집한 실행 로그를 나란히 비교할 수 있습니다.

백엔드를 새로 만드는 쪽에도 문턱이 낮아졌습니다. 이전에는 통신 백엔드를 추가하려면 c10d를 직접 수정해야 했지만, 이제 Python 엔트리 포인트(entry point)로 백엔드를 등록할 수 있고 백엔드 문자열이 자동으로 정규화됩니다. PyProcessGroup 트램폴린이 C++ 구현과 동등한 수준으로 올라와서, 트리 외부(out-of-tree) 백엔드가 batch_isend_irecv, 병합 관리자(coalescing manager), 정리된 *_single 변형까지 포함한 집합 통신 표면 전체를 C++이나 Python 어느 쪽으로도 구현할 수 있습니다.

torch.distributed API 정리

분산 학습 API에서 오래 불편했던 지점들이 함께 정리되었습니다. 프로세스 그룹의 집합 통신 타임아웃을 초기화 이후에 바꿀 수 있는 torch.distributed.set_timeout이 안정 API로 추가되었습니다. 체크포인트 로딩처럼 느린 구간에서 타임아웃을 늘리거나, 반대로 멈춘 랭크가 기본 대기 시간을 다 소진하지 않고 빨리 실패하도록 줄이는 데 쓸 수 있고, 연산별(per-operation) 타임아웃도 지원됩니다. 백엔드별 고급 기능은 torch.distributed.get_backend_impl로 접근하고 훅을 붙여 동작을 커스터마이즈하거나 관측할 수 있습니다. 객체 집합 통신(object collectives)이 torch.load와 같은 weights_only=True 모드를 지원하게 된 것은 학습 클러스터의 보안 측면에서 의미가 있고, 단일 텐서 변형의 이름은 all_to_all_single처럼 _single 접미사를 공유하도록 통일되었습니다.

DTensor 샤딩 규칙의 재작성

DTensor의 샤딩 규칙은 그동안 연산마다 디바이스 메시 전체를 대상으로 작성되었습니다. 규칙 하나가 모든 메시 차원에 걸친 배치(placement) 조합을 전부 열거해야 했고, 메시가 2차원 이상이 되면 작성이 길어지는 데다 미묘하게 틀리기 쉬웠습니다. 2.14는 한 메시 차원이 연산을 어떻게 샤딩하는지만 기술하고 전체 메시로의 확장은 프레임워크에 맡기는 단일 차원(single-dim) 전략 함수로 연산 커버리지를 계속 옮기고 있습니다. 이번에 행렬, 수학, 텐서 연산이 전환되면서 직접적인 register_op_strategy 등록이 158개에서 114개로 줄었고, 샤딩 규칙이 등록된 전체 연산 수는 2026년 1월의 585개에서 1,239개로 늘었습니다.

합성곱(convolution)에도 마지막 공간 차원에 대한 샤딩이 추가되었습니다. 윈도우가 그 차원을 정확히 타일링하는 조건, 즉 제로 패딩과 dilation 1, 커널 폭과 같은 스트라이드, 그리고 커널 폭과 메시 크기의 곱으로 나누어지는 차원일 때, 순방향과 역방향 모두 all-gather로 복제하지 않고 로컬에서 실행됩니다. 단, 새 규칙은 이전 것보다 엄격해서, 우연히 기본 전략에 맞아떨어졌던 기존 어노테이션은 이제 재분배(redistribution)가 필요하다고 보고됩니다. 전환된 연산은 Partial("product")를 더 이상 생성하지 않습니다.

대칭 메모리와 MoE 통신

대칭 메모리(symmetric memory)의 NCCL 백엔드에는 런타임에만 드러나는 구멍이 있었습니다. barrier()가 미구현 오류를 냈고, 할당 후 시그널 패드(signal pad)가 0으로 초기화되지 않아 시그널링 프로토콜이 신뢰할 근거가 없었습니다. 둘 다 수정되었고, 시그널 패드는 CUDA, NCCL, NVSHMEM 세 백엔드 모두에서 대칭 할당의 맨 앞으로 이동했습니다. 재사용되거나 크기가 바뀐 할당이 오염된 패드를 물려받을 수 없게 되었고, 블록 전체가 아니라 패드만 0으로 채우므로 큰 할당이 alloc()마다 전체 버퍼 memset 비용을 내지 않습니다. 남은 제약은 시그널 패드 슬롯이 같은 할당에서 프로세스 그룹 사이에 공유된다는 것입니다. 겹치는 그룹의 동시 barrier는 여전히 서로 간섭할 수 있습니다.

여기에 단방향 get이 추가되었습니다. 다른 랭크에 있는 데이터를 읽으려면 지금까지는 집합 통신이 필요했고, 실제로 데이터가 필요한 랭크가 하나뿐일 때도 모든 랭크가 참여하고 동기화해야 했습니다. get은 상대의 참여도 그룹 전체 동기화도 없이 상대의 대칭 할당을 로컬 목적지 텐서로 직접 복사합니다. NVSHMEM, NCCL 대칭 메모리, CUDA 백엔드에서 동작하고 XPU와 rocSHMEM은 아직 지원되지 않으며, 소스가 dtype과 원소 수가 목적지와 일치하는 랑데뷰(rendezvous)된 대칭 할당이어야 합니다.

MoE 학습을 위한 TokenSwitch도 새로 들어왔습니다. MoE 학습은 각 토큰을 그것이 고른 전문가가 있는 랭크로 보내고 전문가의 출력을 다시 가져오는 데 스텝 시간의 상당 부분을 쓰는데, 팀들은 보통 이 부분을 벤더 커널 라이브러리에 맞춰 역전파까지 직접 구현합니다. TokenSwitchcreate_routing(), dispatch(), combine()이라는 인터페이스로 이를 감싸고, NCCL의 전문가 병렬(expert-parallel) 커널 위에 구현된 TokenSwitchNCCL을 첫 백엔드로 제공합니다. out= 인자 없이 호출하면 dispatch와 combine이 미분 가능한 텐서를 반환하므로 MoE 레이어를 autograd가 추적하는 평범한 Python 코드로 작성할 수 있고, out=을 넘기면 버퍼 재사용 경로를 쓰는 대신 autograd를 포기합니다. 아직 초기 코드입니다. 모듈이 비공개이고 USE_NCCL_EP=1로 NCCL 2.30 핀에 맞춰 빌드해야 하므로, 현재로서는 NVIDIA 전용이고 기본 휠로는 쓸 수 없습니다.

랭크 하나에서만 컴파일하기

분산 학습 잡의 모든 랭크는 같은 모델을 각자 컴파일합니다. 몇 분씩 걸리는 컴파일을 랭크 수만큼 반복해서 지불한 뒤에야 학습이 시작되는 셈입니다. compile-on-one-rank는 컴파일 산출물 하나를 어디서나 재사용할 수 있게 만듭니다. make_fx가 팩토리 연산과 캐스트 연산에 트레이싱 랭크의 디바이스를 굽지 않게 되었고, Inductor의 코드 생성과 Triton 런처가 로드 시점에 디바이스를 해석하므로 생성된 소스가 랭크마다 동일해집니다. cuda:0에서 컴파일한 커널이 cuda:3에서 로드되어 실행됩니다.

DeviceMesh.get_group()도 torchbind ProcessGroup을 그래프에 굽는 대신 메시에서 그룹을 그래프 안에서 가져오도록 바뀌었습니다. 이전에는 이 때문에 그래프를 직렬화할 수 없었습니다. 플래그를 켜면 dist.all_reduce 같은 레거시 집합 통신이 함수형(functional) 형태로 트레이싱됩니다. torchtitan의 실험적 graph_trainer가 의도한 사용 형태를 보여줍니다. 프로세스 하나가 미리 컴파일해서 산출물 하나를 쓰고, 모든 랭크가 시작할 때 그것을 읽어 들이므로 산출물을 만들기 위해 N개 GPU 잡을 띄울 필요가 없습니다. 물론 제약도 있습니다. 이 모드는 프로그램당 가속기 디바이스가 하나라고 가정하며 두 번째 디바이스를 건드리는 그래프는 거부하고, torch.compiler.config.compile_on_one_rank 뒤에서 옵트인으로 남아 있습니다.

컴파일과 내보내기: 동적 shape를 선언으로

@dynamic_spec

어떤 입력 차원이 변하는지 PyTorch에 알려주는 방법은 그동안 진입점마다 달랐습니다. torch.export에는 dynamic_shapes 딕셔너리, torch.compile에는 거친 dynamic= 플래그, make_fx에는 전역 트레이싱 모드가 있었고, 어느 경우든 선언이 호출 지점에 놓여 그것이 기술하는 모델과 멀리 떨어져 있었습니다.

2.14는 torch.fx.experimental.dynamic_spec 아래에 ShapesSpec API를 추가했습니다. 차원 이름을 한 번 짓고(ShapeVar("batch", min=2, max=128)) 여러 입력에서 재사용하며, batch * 2 같은 파생 차원을 만들고 batch % 2 == 0 같은 가정을 붙일 수 있습니다. 세 진입점이 모두 같은 dynamic_shapes= 키워드로 이 명세를 받습니다.

from torch.fx.experimental.dynamic_spec import ShapeVar, ShapesSpec, dynamic_spec

batch = ShapeVar("batch", min=2, max=128)

@dynamic_spec(ShapesSpec({"x": {0: batch}}))
def forward(self, x):
    ...

@dynamic_spec 데코레이터를 함수나 모듈의 forward에 직접 붙이면 torch.compile, strict와 non-strict 양쪽의 torch.export.export, make_fx(tracing_mode="fake")가 호출 지점에 아무것도 넘기지 않아도 이 명세를 가져다 씁니다. 이렇게 선언한 차원은 백킹되지 않은(unbacked) 심볼이 되므로, 컴파일러가 트레이싱할 때 마주친 배치 크기에 조용히 특화(specialize)하지 못합니다. 대가는 shape에 의존하는 분기가 가드와 재컴파일이 아니라 데이터 의존(data-dependent) 오류로 드러난다는 것입니다. API는 실험적이고 아직 움직이는 중입니다. make_fx 지원은 tracing_mode="fake"로 제한되고, 명세를 prefer_deferred_runtime_asserts_over_guards=True와 함께 쓰거나 데코레이터와 호출 지점의 dynamic_shapes= 인자를 동시에 쓰면 오류가 발생합니다.

AOTInductor의 세 가지 개선

같은 가중치를 공유하는 AOTInductor 모델 여러 개를 서빙할 때, 지금까지는 모델 컨테이너마다 GPU에 자기 사본을 할당하고 로드했습니다. 새 C API AOTInductorModelContainerCreateWithExternalConstants는 컨테이너를 만들 때 호출자가 가중치 텐서를 직접 넘기게 하고, AOTI는 상수 로딩을 건너뛰고 호출자의 메모리를 그대로 씁니다. 사본 하나가 여러 모델을 받칠 수 있고 CUDA IPC로 프로세스 사이에 공유할 수도 있습니다. 소유권은 호출자에게 남으므로 그 텐서들이 컨테이너보다 오래 살아야 하며, 아직 C ABI로만 제공되고 Python 진입점은 없습니다. 같은 기반 모델의 변종을 여럿 서빙하는 환경에서는 모델별 가중치 메모리가 공유 할당 하나로 바뀝니다.

컴파일 자체도 정리되었습니다. triton.autotune_at_compile_time=False로 모델을 패키징하면 이전에는 코드 생성이 두 번 돌았습니다. 컴파일하고, 실행해서 커널 메타데이터를 수집하고, 상태를 리셋한 뒤 패키징을 위해 다시 컴파일하는 순서였습니다. 이제는 JIT 래퍼와 AOTI 래퍼 본문을 한 번의 코드 생성 패스에서 내보내고, JIT 본문을 실제 입력으로 한 번 실행해 Triton 커널 구성을 포착한 뒤 패키징되는 소스에 그것을 심습니다. 새 경로에서 torch.condtorch.while_loop이 지원되고, cpp_wrapper가 명시적인 사용자 스트림과 이벤트를 내보낼 수 있게 되었습니다(현재 CUDA 전용이며 CUDA 그래프와 함께 쓸 수 없습니다).

세 번째는 상수 로딩입니다. 모델 가중치를 로드하는 것은 호스트 메모리에서 GPU로 복사하는 일인데, 페이지 가능(pageable) 메모리에서 하는 동기 복사는 디바이스 전체 동기화를 유발해 다른 스트림에서 이미 실행 중인 추론(inference)을 멈춰 세웁니다. AOTInductorSetUsePinnedAsyncConstantsCopy는 상수 로딩과 갱신을 고정(pinned) 스테이징 버퍼를 통과하도록 바꿔 호스트 복사와 디바이스 전송을 중첩시키고, 버퍼 크기를 정하는 동반 호출과 AOTI_COPY_USE_PINNED_ASYNC 환경변수를 폴백으로 제공합니다. 기본은 꺼져 있고 모델이나 컨테이너를 만들기 전에 켜야 합니다. .so를 로드해서 모델이 서빙 준비를 마치기까지의 구간은 그동안 아무 정보가 없었는데, AOTI_LOG_LOADING을 설정하면 복사 타이밍과 고정 풀 진단이 담긴 [AOTI_LOAD] 마커가 출력됩니다.

Helion을 네이티브 DSL로 등록

빠른 GPU 커널을 손으로 쓰는 일은 타일 크기, 루프 순서, 메모리 접근 패턴을 고르고 새 shape와 새 GPU마다 그것을 다시 튜닝하는 작업입니다. Helion은 그 층을 한 단계 올려서, 알고리즘을 Python으로 쓰면 스케줄 공간을 탐색해 Triton 코드를 생성합니다. PyTorch 2.14는 2.13에서 도입된 네이티브 도메인 특화 언어(Domain-Specific Language, DSL) 레지스트리에 Helion을 세 번째 항목으로 등록했습니다. Triton과 CuTeDSL로 작성한 커널이 이미 그럴 수 있듯이 Helion으로 작성한 커널도 ATen 연산을 재정의할 수 있고, torch.backends.python_native.helion으로 제어합니다. 등록에는 helion 패키지와 그 lowering 백엔드가 필요하며 ROCm 빌드에서는 사용할 수 없습니다. 이번 릴리즈에서 Helion으로 라우팅되는 연산은 아직 없고, 이후 릴리즈에서 들어올 Helion 기반 커널 재정의의 토대입니다.

다분기 제어 흐름과 CUDA 그래프

torch.cond는 두 갈래 분기를 표현하므로 n개 분기를 쓰려면 조건문을 중첩해야 했고, 그러면 트레이싱된 그래프가 커지면서 의도도 흐려졌습니다. torch.switch는 인덱스로 다분기하는 새 고차 연산(higher-order op)으로, 공유된 피연산자가 분기마다 다시 리프트되지 않도록 Dynamo에서 리프트된 인자를 중복 제거합니다. torch.cond 중첩이 실질적인 장벽이었던 MoE 아키텍처의 트레이싱에서 특히 도움이 됩니다. 아직 프로토타입이어서 autograd는 지원되지 않습니다.

torch.while_loop은 CUDA 그래프에 담을 수 있게 되었습니다. 데이터에 따라 반복 횟수가 달라지는 루프는 워크로드를 CUDA 그래프로 완전히 캡처할 수 없는 표준적인 이유 중 하나였습니다. 몇 번 돌릴지 결정하려고 디바이스에서 호스트로 값을 복사해야 하고, 그 지점에서 캡처가 끊어졌습니다. 이제 CUDA의 while 조건 노드를 이용해 torch.while_loop을 그래프로 캡처할 수 있습니다. 조건은 노드가 추가되기 전 부모 스트림에서 평가되고 본문이 실행될 때마다 다시 평가되므로, 캡처된 그래프 하나가 재생 시점에 런타임에 결정된 횟수만큼 반복합니다. 이것 자체가 처리량 개선은 아닙니다. 요점은 루프 때문에 그래프 캡처를 포기하지 않아도 된다는 것이고, 길이가 가변인 인덱스 텐서에 대한 리덕션이나 개수가 변하는 패킹된 시퀀스에 적용하는 손실 계산 같은 경우가 한 그래프 안에 남습니다. 고정된 최대 반복 횟수와 텐서만 담긴 carried input 같은 기존 while_loop 제약은 그대로입니다.

Apple Silicon: 어텐션 다음은 선형대수

MPS의 선형대수는 그동안 Apple의 MPSGraph 프리미티브에 기대거나, 기본을 넘어서는 연산에서는 CPU로 완전히 폴백했습니다. 수치 계산 코드에서 CPU와 MPS를 왕복하는 것이 흔한 성능 저하 원인이었던 이유입니다. 2.14는 그 구멍 여럿을 네이티브 Metal 커널로 대체했습니다.

SVD, eigh, lstsq가 float32와 complex64에 대해 야코비 방식 커널로 네이티브 실행됩니다. Metal에 double 타입이 없으므로 float64는 CPU로 폴백하고, GPU 실행 오버헤드가 이득보다 큰 작은 행렬과 작은 배치도 CPU로 갑니다. 이 세 연산이 네이티브로 내려오면서 그것에 의존하는 matrix_rank, pinv, cond와 노름 계산도 함께 살아났습니다. 에르미트(Hermitian)가 아닌 eigeigvals는 다음으로 미뤄졌습니다.

콜레스키 분해는 matmul2d 기반 trailing update를 쓰는 더 빠른 패널 분해 알고리즘을 받아 크기에 따라 대략 1.2배에서 2.8배 빨라졌고, dtype 가드가 없어 복소수 타입에서 조용히 틀린 결과를 낼 수 있었던 문제도 함께 고쳐졌습니다. lu_factorlu_solve는 Apple의 MPSMatrixDecompositionLU에서 직접 작성한 Metal 커널로 옮겨졌는데, 제출자가 측정한 연산 수준 속도 향상은 작은 배치 행렬에서 100배 이상, 큰 단일 행렬에서 2배에서 9배입니다. geqrf가 추가되고 linalg_qr은 CPU와 CUDA가 쓰는 디바이스 중립 코드 경로를 공유하도록 리팩터링되었으며, matrix_explinalg.polar(역방향 포함)이 MPS에서도 사용 가능해졌습니다. 다만 matrix_exp는 대략 512×512 이상에서만 CPU를 앞섭니다.

성능 쪽에서 실사용에 가장 크게 닿는 변화는 디코딩 경로입니다. 단일 토큰 디코드는 F.linear[B, 1, K] 모양의 활성화를 넘기는데, 이 모양이 MPS의 빠른 경로에서 벗어나 있어서 수정 내역에 따르면 bf16과 fp16에서 8.5배 느려지고 있었습니다. 시퀀스 길이 1인 경우가 이제 올바르게 라우팅되고, 자기회귀(autoregressive) 디코딩을 지배하는 벡터 행렬 모양을 받치는 새 GEMV 커널이 추가되었습니다.

프리필(prefill) 어텐션에는 macOS 26.2에서 새로 제공되는 Apple의 Metal Performance Primitives(MPP)를 활용한 두 번째 커널이 들어왔습니다. MLX가 M5 칩에서 쓰는 접근을 이식하면서 이전 세대 Apple Silicon까지 확장한 것으로, fp16과 bf16 입력에 head 차원이 64, 96, 128, 256이고 쿼리 길이가 8보다 클 때 적용됩니다(macOS 26.2 이상, 그 외 shape와 dtype은 기존 simdgroup-matrix 커널을 계속 사용). 작성자의 벤치마크에서 head 차원과 시퀀스 길이 전반에 걸쳐 이전 커널 대비 대략 2배에서 4배의 속도 향상이 나타났고, head 차원이 작고 시퀀스가 길수록 이득이 큽니다. 다만 PyTorch 팀은 이 커널의 성능 이득이 Apple M5 하드웨어에서 가장 확실하게 확인된다고 밝혔습니다. 기반이 되는 레인별(per-lane) 데이터 레이아웃이 M5를 기준으로 검증되었고, 이전 세대 Apple Silicon에서 어떻게 동작하는지는 이번 릴리즈에서 독립적으로 검증되지 않아 위 수치와 다를 수 있습니다.

FlexAttention은 2.13에서 MPS에 도착한 뒤 실제 모델에 쓰이면서 드러난 구멍들이 메워졌습니다. KV 배치 브로드캐스팅이 추가되어 키와 값 텐서를 쿼리 배치 전체에서 공유할 수 있게 되었는데, 공유 KV 캐시에 여러 시퀀스를 서빙해야 하는 페이지드 어텐션(paged attention)의 전제 조건입니다. flex_attention이 log-sum-exp와 최대 점수 보조 출력을 결과와 함께 반환할 수 있게 되었고, score_modmask_mod 함수가 동적 shape 값(SymInt)을 직접 캡처할 수 있어 런타임 크기로 만든 마스크가 torch.compile(dynamic=True)에서 shape가 바뀔 때마다 재컴파일을 유발하지 않습니다.

마지막으로 ctc_loss가 MPS에서 순방향과 역방향 모두 처음 지원됩니다. 음성 인식이나 OCR처럼 정렬 없이(alignment-free) 학습하는 시퀀스 모델의 손실 함수인데, 그동안 이 연산 하나 때문에 Mac 사용자가 CPU로 폴백해야 했습니다. 구현은 가변 길이(패딩된) 배치 처리를 포함해 CUDA 커널과 같은 로그 영역(log-domain) 방식을 따릅니다.

이 밖에 index_add, index_select, argmin, argmax, conv3d, median, nanmedian, linspace, arange, nan_to_num, log_sigmoid, sigmoid_backward, mish, GLU가 MPSGraph에서 직접 작성한 Metal 컴퓨트 커널로 이관되었고, 리덕션은 전체 리덕션, 내부 차원 리덕션, strided와 배치된 외부 리덕션, 작은 차원과 좁은 커널, argmaxargmin의 split-K 경로를 다루는 다섯 부분으로 재작성되었습니다. 네이티브 Metal 경로는 MPSGraph의 연산별 컴파일 비용을 없애고 스레드 디스패치와 메모리 접근 패턴을 PyTorch가 직접 제어하게 합니다.

컴파일러와 즉시 실행 모드의 오버헤드

성능 개선 중에는 사용자가 코드를 바꾸지 않아도 적용되는 것들이 있습니다. 가장 눈에 띄는 것은 Inductor의 simple_overlap 재배치 패스가 옵트인에서 기본값으로 바뀐 것입니다. 이 패스는 집합 통신을 독립적인 계산과 교차 배치해 통신이 임계 경로에 남지 않게 하는데, 이제 Inductor로 컴파일한 분산 학습 워크로드가 설정 변경 없이 더 나은 GPU 활용률을 얻습니다.

콤보 커널(combo kernel)은 작은 커널 여러 개를 한 번의 실행으로 묶는 기능인데, 묶음 안에 아주 큰 리덕션 하나가 있으면 그것이 커널 전체의 모양을 결정해 버리는 문제가 있었습니다. 이제 큰 리덕션은 콤보 분할에서 빠지고, 콤보 리덕션은 동적 RBLOCK 스케일링을 받으며, 서브 커널 본문은 레지스터 압박을 낮추기 위해 인라인되지 않는 디바이스 함수로 생성됩니다. 콤보 커널마다 본문이 공유되고 split-reduction 휴리스틱은 GB200에 맞춰 튜닝되었습니다.

Dynamo의 호출당 고정 비용도 여러 지점에서 줄었습니다. PyTorch 팀에 따르면 컴파일된 영역이 작게 많이 나뉜 모델에서는 그래프 품질보다 이 고정 비용이 더 중요합니다. compile_wrapper가 호출마다 DispatchKeySet pybind 작업을 반복하지 않게 되었고, torch._dynamo.disable에 더 저렴한 경로가 생겼으며, pregraph 프로파일러 마커는 항상 발행되는 대신 활성 프로파일러가 있을 때만 발행됩니다. 사용되지 않는 함수 입력에 대한 가드 생성은 생략되고, invoke_subgraph 재사용 조회는 dataclass나 namedtuple 같은 pytree 인자에서 더 빨라졌습니다.

즉시 실행(eager) 모드의 핫 경로도 함께 저렴해졌습니다. PyObject 디스패치가 최적화되고, AOTAutograd가 역방향을 위해 그래프 입력 뷰를 저장할 때 비싼 Tensor.detach()를 피하고, autograd는 프로파일러가 꺼져 있으면 at::Tensor를 복사하지 않으며, addmm은 C와 D가 서로 다를 때 디바이스 간 복사를 하지 않습니다. CPU의 quantilenanquantile은 전체 정렬 대신 부분 선택(partial selection)을 사용합니다.

학습 그래프에 대한 지역성 재배치도 선택지로 열렸습니다. Inductor의 post-grad 지역성 재배치 패스인 reorder_for_locality는 추론에서만 돌았는데, 새 reorder_for_locality_in_training 설정으로 학습 그래프에도 적용할 수 있습니다(기본은 꺼짐).

코어 API와 자동 미분

torch.linalg에 두 함수가 추가되었습니다. torch.linalg.polar는 cuSOLVER의 QDWH 알고리즘으로 극 분해(polar decomposition)를 계산하며 CPU, CUDA, MPS에서 역방향 공식을 갖추었으므로 분석용이 아니라 학습 루프 안에서 쓸 수 있습니다. torch.linalg.matrix_sqrth는 대칭 또는 에르미트 양의 정부호(positive-definite) 행렬의 제곱근을 계산하는데, 그동안 고윳값 분해를 손으로 조합해야 했던 경우입니다. 배치 입력, autograd, vmap, torch.compile을 지원합니다.

자동 미분(autograd) 쪽에는 그래프가 만들어지는 방식을 들여다보고 제어할 수 있는 확장점이 셋 추가되었습니다. torch.autograd.graph.node_creation_hook은 autograd 노드가 만들어질 때마다 발동하므로, 도구가 나중에 그 맥락을 재구성하는 대신 그래프 구축 시점에 메타데이터를 붙이거나 훅을 등록할 수 있습니다. 이 기능을 만든 동기는 역방향 패스의 메모리 사용량을 그것을 만들어 낸 순방향 영역으로 귀속시키는 것이었습니다. ctx.set_output_grad_dtype은 커스텀 autograd.Function이 출력의 저장 dtype과 별개로 그 출력에 들어오는 변화도(gradient)의 dtype을 선언하게 해 주는데, 둘이 일치하지 않는 혼합 정밀도 함수를 위한 것입니다. cdistpdist에 이중 역전파(double backward)가 구현되어, 지금까지 아예 실패했던 create_graph=True 사용, 즉 쌍별 거리 계산을 거치는 헤시안(Hessian), 변화도 페널티, 헤시안 벡터 곱이 가능해졌습니다.

이 밖에 눈여겨볼 작은 추가들이 있습니다.

  • torch.utils.checkpoint.checkpoint가 즉시 실행 모드에서 데코레이터와 커링(curried) 호출 규약을 받습니다. 체크포인트 설정을 감싸는 함수의 인자와 분리해 쓸 수 있습니다.

  • 읽기 전용 DLPack 내보내기와 ReadOnlyTensorWrapper가 추가되어, 소비자에게 변경하면 안 되는 텐서를 넘길 수 있습니다.

  • Generator.philox_state가 Philox RNG 상태 예약을 Python에 노출합니다. Python으로 작성한 커널이 CUDA 그래프 캡처와 재생을 통과해도 올바른 Philox 카운터 범위를 예약할 수 있습니다.

  • torch.acceleratorinitial_seed, get_rng_state, get_rng_state_all이 추가되어 CUDA 전용 RNG API와의 격차가 줄었습니다.

  • LBFGSmaximize를 지원하고, 빈 파라미터 그룹에서는 아무 동작도 하지 않습니다.

  • 2.13에서 도입된 linear_cross_entropy가 청크(chunked) 경로에서 확률 타깃을 지원합니다.

  • 스케일된 내적 어텐션(SDPA)이 랭크 3 입력에서 math 경로로 폴백하는 대신 융합된 CUDA 백엔드로 디스패치합니다. 배치 차원이 없거나 이미 평탄화된 텐서를 넘기는 호출자가 reshape 없이 융합 커널을 쓰게 되면서, 배치 차원이 빠져 있으면 조용히 빠른 커널을 우회하던 흔한 성능 함정이 사라졌습니다.

  • 복소수 텐서를 사용하는 프로그램에 대한 torch.compile 지원이 실험적으로 추가되었습니다. 지원되는 복소수 연산은 컴파일러 백엔드가 최적화할 수 있는 실수 계산으로 분해되며, 신호 처리, 과학 계산, 복소수 신경망 같은 워크로드가 컴파일된 실행의 이득을 받습니다. 모든 복소수 연산이 지원되지는 않고, 진행 상황은 기능 추적 이슈에서 확인할 수 있습니다.

플랫폼: ROCm, Intel XPU, 그리고 프로파일링

AMD ROCm 쪽에서는 MoE 모델이 그동안 놓치고 있던 것을 받았습니다. Inductor의 Triton 컴파일 그룹 GEMM은 NVIDIA SM90 이상 하드웨어로 제한되어 있었고, ROCm은 hipBLASLt와 rocBLAS 호출을 for 루프로 도는 더 느린 경로로 폴백했습니다. 이번 릴리즈는 그 Triton lowering을 스케일된 FP8 변형까지 포함해 ROCm으로 가져왔고, Composable Kernel GEMM 템플릿이 사전 컴파일뿐 아니라 JIT cpp_wrapper 컴파일에서도 동작하게 했습니다. 여기에 AMD의 분석적 타일 크기 선택기인 Origami가 ROCm max-autotune에서 기본으로 켜져서, 전체 자동 튜닝 스윕을 돌리지 않고 지연 시간 모델에서 최적에 가까운 GEMM 구성을 고를 수 있습니다.

RDNA3 GPU(MI 계열 데이터센터 라인이 아닌 Radeon 워크스테이션과 컨슈머 카드)의 FlexAttention은 아키텍처에 맞춰 튜닝되지 않은 타일 크기를 쓰고 있었습니다. 이번에 RDNA3용으로 프로파일링한 시퀀스 길이 인식 타일 구성이 추가되어, 수백 토큰 범위에서 대략 2배에서 8배 낮은 지연 시간을 얻고 아주 짧은 시퀀스에서는 회귀가 없습니다. 또한 AMD gfx1250에 대한 초기 기술 프리뷰 지원이 추가되었지만 CK SDPA와 GEMM, FP8 그룹 GEMM, int4 행렬 곱은 아직 지원되지 않습니다.

Intel XPU에서는 XPU Graph의 그래프 캡처와 재생 오버헤드가 줄어 Intel Arc B 시리즈 이상의 Intel GPU에서 그래프 기반 학습과 추론 성능이 개선되었고, oneAPI 2026.1 이상으로 빌드한 경우 PVC가 아닌 디바이스에서 네이티브 기록 모드를 쓸 수 있습니다. scaled_mm에 MXFP8과 MXFP4 지원이 추가되어 차세대 Intel GPU를 위한 소프트웨어 준비가 앞당겨졌고, XPU 대칭 메모리 백엔드가 활성화되면서 Intel GPU에서 비동기 텐서 병렬(Async Tensor Parallelism)이 가능해졌습니다. 관측 도구로는 프로세스별 Intel GPU 메모리 사용량을 조회하는 torch.xpu.list_gpu_processes()가 추가되었고, WSL2에서 Ubuntu 24.04와 26.04가 지원 목록에 들어왔습니다.

C++ 확장을 만드는 쪽에는 torch::stable 표면이 넓어졌습니다. torch::stable에 정의된 API 부분집합을 쓰는 C++ 애플리케이션은 릴리즈 사이의 ABI 호환성에 의존할 수 있는데, 2.13의 torch::stable::Generator에 이어 이번에는 PyObjecttorch::stable::Tensor 사이의 변환, Tensor::has_storage, 그리고 bitwise_and, bitwise_or, left_shift, right_shift, permute, view_dtype, index_select, floor_divide, is_pinned의 안정 오버로드가 추가되었습니다. fastAtomicAddisinf, isnan을 포함한 유틸리티가 헤더 전용 torch::headeronly로 옮겨져서, 확장 작성자가 libtorch에 링크하지 않고도 이들을 쓸 수 있습니다.

프로파일링에서는 고정(pinned) CPU 메모리가 메모리 스냅샷에 들어왔습니다. 메모리 스냅샷은 한동안 디바이스 할당을 다뤄 왔지만, 호스트에서 디바이스로의 전송을 준비하는 데 쓰이는 고정 호스트 메모리는 대상이 아니었습니다. 그 메모리가 예상보다 늘어나도 이미 쓰고 있는 도구에서는 볼 방법이 없었던 셈입니다. 고정 버퍼는 추적을 놓치기도 쉽습니다. CUDA 그래프가 캡처된 복사에 고정된 호스트 주소를 요구하기 때문에 보통 한 번 할당해서 프로세스가 사는 동안 계속 들고 있습니다. torch.cuda.memory._record_memory_history()record_host=True를 넘기면 고정 할당도 포착되어 기존 디바이스 데이터와 함께 host_segmentshost_traces 키로 노출됩니다. 단, memory_viz 시각화 도구는 아직 호스트 데이터를 그리지 않고, PyTorch 할당자 밖에서 cudaHostRegister를 직접 호출해 만든 할당은 포착되지 않습니다.

CUDA 그래프의 관측 도구도 여럿 늘었습니다. 프로파일러나 메모리 추적기처럼 밖에서 CUDA 그래프를 지켜보고 싶은 도구는 그래프별 훅만 등록할 수 있었고, 그래프가 도구가 아니라 Inductor나 NCCL이 만든 것이면 도움이 되지 않았습니다. 이제 프로세스의 모든 그래프에 대해 발동하는 모듈 수준 훅(캡처 시작과 종료, 재생 시작과 종료, 인스턴스화, 소멸)이 추가되었고, CUDAGraph에 정리 작업이나 객체 수명을 그래프 자신의 수명에 묶는 register_destroy_callbackretain_object도 생겼습니다. 콜백이 그래프가 여전히 참조하는 메모리를 해제한다면 synchronize_before_release=True를 넘겨야 합니다. 해체가 비동기이므로 재생이 진행되는 중에 해제하면 use-after-free가 됩니다.

CUDA 그래프 캡처가 메모리 풀 하나에만 묶여 있던 제약도 풀렸습니다. 캡처 중에 torch.cuda.use_mem_pool()로 보조 풀에 들어갈 수 있고 그래프가 그 풀들을 모두 유지하므로, 대칭 메모리 버퍼가 CUDA 그래프 안에서 살아남아 전용 풀로 할당하는 분산 워크로드의 그래프 캡처가 가능해집니다. use_mem_pool이 스레드 ID로 할당을 라우팅하는 기존 제약은 남아 있어서, 그 안에서 멀티스레드 autograd로 .backward()를 호출하면 역방향 할당이 풀로 가지 않습니다.

Python 3.15 휠, 그리고 torch.compile이 아직 안 되는 이유

PyTorch 2.14는 자유 스레드(free-threaded, no-GIL) 빌드인 3.15t를 포함해 Python 3.15에 대한 바이너리 지원을 모든 플랫폼으로 확장했습니다. 2.13에서 Linux에 먼저 제공되었던 것이 이번에 Windows와 Apple Silicon macOS로 넓어진 것입니다. 휠은 x86_64와 aarch64 Linux, Windows, Apple Silicon macOS에 대해 CPU, CUDA, ROCm, XPU 빌드를 포함해 게시되고, torchvision 0.29.0도 같은 플랫폼 조합에 대해 3.15와 3.15t 휠을 함께 제공합니다.

주의할 점이 하나 있습니다. Python 3.15와 3.15t 휠은 PyPI에 게시되지 않고 download.pytorch.org에서만 받을 수 있습니다.

# CPU
pip3 install torch --index-url https://download.pytorch.org/whl/cpu

# CUDA (CUDA 버전을 지정, 예: cu126 / cu130)
pip3 install torch --index-url https://download.pytorch.org/whl/cu130

# ROCm (ROCm 버전을 지정)
pip3 install torch --index-url https://download.pytorch.org/whl/rocm7.14

# XPU
pip3 install torch --index-url https://download.pytorch.org/whl/xpu

자유 스레드 빌드도 같은 명령을 씁니다. 3.15t 인터프리터에서 실행하면 pip가 cp315t 휠을 자동으로 해석합니다.

더 중요한 제약은 2.14의 Python 3.15 지원이 즉시 실행 모드 전용 이라는 것입니다. Python 3.15에서 torch.compile을 호출하면 조용히 폴백하지 않고 RuntimeError를 냅니다. 성능이 소리 없이 사라지는 대신 제약이 즉시 드러나도록 한 선택입니다. torch.compile에 의존하는 워크로드라면 당장은 Python 3.14 이하에 머물러야 합니다. 3.15용 Dynamo 지원은 활발히 개발 중이고 새 인터프리터를 위한 바이트코드와 심볼릭 변환 처리가 이미 반영되었으며, 진행 상황은 pytorch/pytorch#184352에서 추적됩니다.

도메인 라이브러리: 릴리즈가 분리되기 시작했다

이번 릴리즈에서 PyTorch 본체와 같은 날 나온 도메인 라이브러리는 torchvision 0.29.0 하나이고, 하루 뒤 torchtitan 0.3.0이 나왔습니다. torchao 0.18.0, executorch 1.4.1, torchcodec 0.16.0, tensordict 0.14.0은 8월에 각자의 일정으로 먼저 출시되었습니다. 이렇게 흩어진 것 자체가 이번 릴리즈에서 봐야 할 변화입니다.

torchvision 0.29의 두 가지 변경이 그 이유를 설명합니다. 첫째, torchvision이 torch 2.14에 대해 ABI 안정 이 되었습니다. torchvision 0.29는 앞으로 나올 torch 2.15, 2.16 등과 호환되므로 torch를 올릴 때 torchvision을 새로 설치할 필요가 없습니다. torchvision 팀은 이 때문에 PyTorch와 동기화된 릴리즈를 중단할 수 있다고 밝혔고, 다만 라이브러리 자체는 계속 활발히 유지보수하며 같은 주기가 아닐 뿐 릴리즈는 계속 낸다고 덧붙였습니다.

둘째, torchvision.io의 이미지 디코더와 인코더가 폐기(deprecated) 되었습니다. 향후 릴리즈에서 제거될 예정이고, 기능은 torchcodec 0.16 이상으로 옮겨갔습니다. torchcodec은 원래 영상 디코딩 라이브러리로 시작했는데, 0.16에서 JPEG(CPU와 CUDA), PNG, WebP, GIF, AVIF, HEIC를 네이티브로 디코딩하고 인코딩하게 되면서 이미지까지 담당하게 되었습니다. 대부분의 디코딩 API는 이름이 같으므로 마이그레이션 부담은 크지 않고, torchvision 팀이 마이그레이션 가이드를 제공합니다.

정리하면 PyTorch의 미디어 처리 라이브러리 세 개의 역할이 이번에 명확히 갈렸습니다. torchcodec이 이미지, 영상, 오디오 모든 미디어의 디코딩과 인코딩을 담당하고, torchvisiontorchaudio는 변환(transforms)에 집중합니다.

학습 스택 쪽에서는 torchtitan 0.3.0이 검증된 버전 조합을 명시하고 있어 참고가 됩니다.

구성요소 torchtitan 0.3.0이 검증한 버전
Python 3.11, 3.12
PyTorch 2.14.0
torchvision 0.29.0
torchao 0.18.0

torchtitan 0.3.0 자체도 2.14의 기능과 맞물립니다. spmd_types가 기본 SPMD 백엔드가 되어 Llama 3, Qwen3, DeepSeek V3, GPT-OSS, Flux, Qwen3.5, Kimi K2.7, Muse Glimmer에 선언적 상태와 활성값 샤딩을 제공하고, GraphTrainer가 순방향과 손실, 역방향 스텝을 하나의 그래프로 캡처해 한 번 사전 컴파일한 뒤 랭크 사이에서 재사용합니다. 위에서 살펴본 compile-on-one-rank가 노리는 사용 형태가 바로 이 부분입니다. MoE 실행은 라우팅, 토큰 이동, 전문가 계산을 분리하는 통합 토큰 디스패처 인터페이스로 재구성되었고, TitanRL이라는 실험적 강화학습 워크플로가 비동기와 멀티턴 롤아웃, 연속 배칭을 추가했습니다.

마이그레이션에서 확인해야 할 것들

기존 코드를 2.14로 올릴 때 확인이 필요한 변경들을 모았습니다.

제거된 API

  • 폐기 상태였던 torch.cholesky()Tensor.cholesky()가 제거되었습니다. torch.linalg.cholesky()를 사용합니다.

  • 폐기 상태였던 torch.qr()Tensor.qr()가 제거되었습니다. torch.linalg.qr()를 사용합니다.

  • 프로파일러에서 폐기 상태였던 use_cuda 인자가 torch.profiler.profiletorch.autograd.profiler.profile에서 제거되었습니다. 패턴 매처, BasicEvaluation, profiler_metrics, profiler_measure_per_kernel도 제거되었습니다.

  • Dynamo의 tvm 백엔드가 TVM의 relax 프런트엔드만 사용합니다. relay 경로는 제거되었습니다.

  • torch.nn.LinearCrossEntropyOptionsacc_policy="balanced"를 더 이상 받지 않습니다. "compact"가 CUDA에서 같은 가중치 변화도 누적 정밀도를 더 적은 메모리로 제공하고 "auto""balanced"를 고른 적이 없었기 때문입니다. 이제 ValueError가 발생합니다.

  • C++ 프런트엔드에서 인자 없는 c10::Scalar::isIntegral()c10::isIntegralType(ScalarType) 오버로드가 제거되었습니다.

동작이 달라진 것

  • clamp와 min/max 계열의 경계 부분 변화도(subgradient)가 선택된 디스패처 스키마의 입력 공간을 따릅니다. 미분 불가능한 경계나 동점(tie)에서 계산되는 변화도가 영향을 받습니다. 스칼라 clamp 경계는 고정 파라미터이므로 등호 지점에서 입력 변화도가 1에서 최소 노름 부분 변화도인 0으로 바뀝니다. 텐서 경계는 미분 가능한 입력 공간의 일부이므로, clamp, clamp_min, clamp_max는 일반적인 동점에서 변화도를 입력에 전부 주는 대신 입력과 경계에 균등하게 나눕니다. fminfmax도 같은 균등 분배를 쓰고, min/max 계열의 순방향 모드 자동 미분도 이 규칙에 맞춰졌습니다. 기존 동점 처리에 의도적으로 의존하는 코드는 torch.where(value >= bound, value, bound)처럼 명시적으로 표현할 수 있습니다.

  • new_group()을 직접 구현한 커스텀 Python 프로세스 그룹은 이제 backend 키워드 인자를 받아야 합니다. PyTorch가 해석된 백엔드를 전달해 커스텀 구현이 요청된 서브그룹을 올바르게 만들 수 있게 하기 위한 변경으로, 이 파라미터가 없는 기존 구현은 TypeError를 냅니다. 백엔드가 하나뿐이면 인자를 받고 무시해도 됩니다.

  • NCCL 대칭 메모리 풀이 register_mem_pool(..., symm=True) 이후에 할당된 세그먼트를 대칭 윈도우로 자동 승격하지 않습니다. CUDA 할당자 콜백에서 그런 늦은 세그먼트를 등록하면 할당자 락을 쥔 채로 일부 랭크에서만 집합 NCCL 연산을 호출해 복구 불가능한 hang이 발생할 수 있었기 때문입니다. 새로 할당된 세그먼트가 대칭 윈도우 알고리즘을 쓰려면 그 할당을 만든 뒤 풀을 집합적으로 등록 해제하고 다시 등록해야 합니다.

  • 실험적 torch.distributed.split_group()에서 그룹에 속하지 않은 랭크가 None 대신 GroupMember.NON_GROUP_MEMBER를 받습니다.

  • bfloat16의 복소수 타입 승격이 torch.complex64 대신 새 torch.bcomplex32 셸 dtype을 사용합니다.

  • Python 함수 이벤트가 프로파일러의 key_averages()에서 기본적으로 제외됩니다. 프로파일러 출력이 눈에 보이게 달라집니다.

  • 희소(sparse) 텐서가 weights_only로 로드될 때 일관성 검증을 받습니다.

폐기 예고

  • TorchScript API가 보통 숨겨지는 DeprecationWarning 대신 눈에 보이는 FutureWarning을 냅니다. TorchScript는 2.10부터 폐기 상태이고 import 경로에서도 제외됩니다. 대체 경로는 torch.exportExecuTorch입니다.

  • 선택적 활성값 체크포인팅(selective activation checkpointing)이 앞으로 주변의 saved_tensors_hooks를 기본적으로 존중하도록 바뀝니다. 새 respect_saved_tensors_hooks 인자로 동작을 명시적으로 선택할 수 있습니다.

  • 분산 학습에서 _set_pg_timeouttorch.distributed.set_timeout으로, torch.distributed.config.compile_on_one_ranktorch.compiler.config.compile_on_one_rank로 대체됩니다. setSequenceNumberForGroup은 폐기된 no-op이 되고 control collectives 구현은 제거되었습니다.

  • CUDA green context의 setpop이 폐기되었습니다. green context를 활성화하려면 커스텀 스트림을 사용합니다. green context 자체는 CUDA Python 바인딩으로 옮겨졌습니다.

  • 프로파일러의 with_modules 옵션이 폐기되어 FutureWarning을 냅니다. profiler_metricsprofiler_measure_per_kernel은 CUPTI 범위 프로파일링을 더 이상 활성화하지 않습니다.

  • torch._dynamo.config.enable_faithful_generator_behavior가 폐기되어 no-op이 되었습니다.

  • CUDAGraph.register_generator_state()가 폐기되었습니다. CUDA 그래프가 캡처 중 첫 RNG 사용 시점에 생성기 상태를 지연 등록합니다.

빌드와 플랫폼 지원 현황

기능 외 변경 중 환경 구성에 영향을 주는 것들을 정리하면 다음과 같습니다.

구성요소 2.13 2.14
CUDA 12.6, 13.0, 13.2 12.6, 13.0, 13.2 (변동 없음)
기본 휠 CUDA 13.0 CUDA 13.0 (변동 없음)
ROCm 7.1, 7.2 7.2, 7.14 (7.1 지원 종료, 7.14는 TheRock 경유)
Python 3.10 ~ 3.15 (3.14t, 3.15t 포함) 변동 없음
C++ 표준 C++20 변동 없음

빌드 시스템이 setuptools에서 scikit-build-core로 이전했고, Windows와 macOS 휠 빌드가 Python 파이프라인으로 리팩터링되었습니다. setup.py는 이제 폐기 안내용 shim이므로 PyTorch를 소스에서 빌드할 때는 pip나 python -m build를 사용해야 합니다. ROCm 7.14 휠은 TheRock pip SDK에서 RPATH 기반 라이브러리 해석으로 빌드되고, manywheel은 4GB를 넘는 휠에서 발생하던 잘못된 ZIP64를 고치기 위해 auditwheel로 재패키징되며, 도구는 rocm_smi에서 amd_smi로 이전했습니다.

의존 라이브러리는 cuDNN이 9.24로 올라가면서 conv engine 5가 다시 활성화되었고, oneDNN은 3.12.3, XPU 지원 패키지는 2026.1로 올라갔습니다. CI와 플랫폼 커버리지에는 네이티브 linux-riscv64 빌드 이미지, B200 벤치마크 워크플로, P2P IPC 테스트를 위한 전용 H100 fabric 러너, Intel BMG 클라이언트 스모크 테스트가 추가되었습니다. Inductor는 NVIDIA의 차세대 아키텍처인 Rubin(sm_107)을 튜닝된 벡터화 원소별 커널로 타깃합니다.

릴리즈 주기와 Q&A 웨비나

2026년부터 PyTorch의 릴리즈 주기는 분기 1회에서 2개월 1회로 단축되었습니다. 2.14는 그 주기의 네 번째 릴리즈이고, RELEASE.md에 공개된 이후 일정은 다음과 같습니다. 앞으로의 날짜는 잠정치입니다.

버전 릴리즈 브랜치 분기 릴리즈 예정일
2.14 2026년 8월 10일 2026년 9월 2일 (출시 완료)
2.15 2026년 9월 28일 2026년 10월 28일
2.16 2026년 11월 23일 2026년 12월 22일

이번 릴리즈에 대한 질문은 2026년 9월 17일 목요일에 열리는 Q&A 웨비나에서 다룹니다. Andrey Talman(Meta), Natalia Gimelshein(Meta), Joe Spisak(Reflection AI)이 패널로, Chris Gottbrath(Gottbrath Tech)가 모더레이터로 참여해 2.14 릴리즈 개요를 소개하고 커뮤니티의 질문에 답합니다.

오프라인 행사로는 2026년 10월 20일과 21일 미국 캘리포니아 산호세에서 PyTorch Conference North America가 열립니다. 컴파일러와 런타임, 분산 통신, 디바이스 이식성, 릴리즈 엔지니어링, CI, 관측성, 가속기 통합, 기여자 인프라를 다루는 세션이 준비되어 있습니다.

:scroll: PyTorch 2.14 출시 공지 블로그

:github: PyTorch 2.14 출시 노트 (Release Note)

:github: torchvision 0.29.0 출시 노트

:github: torchtitan 0.3.0 출시 노트

더 읽어보기




이 글은 GPT 모델로 정리한 초안을 바탕으로 한 것으로, 원문의 내용 또는 의도와 다르게 정리된 내용이 있을 수 있습니다. 관심있는 내용이시라면 원문도 함께 참고해주세요! 읽으시면서 어색하거나 잘못된 내용을 발견하시면 댓글로 알려주시기를 부탁드립니다. :hugs:

이 글은 :pytorch:파이토치 한국 사용자 모임:south_korea:이 직접 정리한 글입니다. 새 글을 놓치지 않으시려면 텔레그램(Telegram)이나 Slack/Discord/Teams/Dooray/GoogleChat 등으로 알림을 받으시고, 회원으로 가입하시면 주요 글들을 이메일:love_letter:로도 보내드립니다! :smiley:

:wrapped_gift: 아래:down_right_arrow:쪽에 좋아요:+1:를 눌러주시면 새로운 소식들을 정리하고 공유하는데 힘이 됩니다~ :star_struck: