Surface Laptop Ultra(Arm 기반 Windows, RTX Spark)에서 측정: PyTorch 2.14.1+cu132는 GPU에서 작동했고; torchaudio만 예외였으며, 일치해야 할 것은 버전 번호가 아니었다.
이 글은 제가 원래 Zenn에 일본어로 게시했던 기사(ComfyUI を Intel Arc から Arm の WSL2 へ。同じ requirements でも部品の版は揃わなかった)를 영어로 각색한 것입니다. 측정 및 결론은 제가 내린 것이며, 번역과 텍스트 재구성은 AI 도구를 사용하여 도움을 받았고, 수치는 원본과 대조했습니다.
간단 요약: 동일한 requirements.txt가 동일한 패키지 버전을 제공하지 않았으며, 패키지가 설치되지 않을 때 확인해야 할 것은 버전 번호가 아니라 CUDA 빌드였다.
TL;DR
- WSL2 on Windows on Arm 내부에서 공식 PyTorch 2.14.1+cu132(Linux Arm build)는 GPU에서 ComfyUI를 실행했다. 모델을 이미 로드한 상태에서 재그림 (단일 이미지의 종단 간 시간이 아닌, 샘플링 + 디코드 + 저장)은 이전 Intel Arc 노트북 대비 50.87초 대 21.60초가 소요되어 약 2.4배 빨랐다.
- torchaudio만 설치되지 않았다. 처음에는 torch와 같은 번호(2.14.1)를 가진 torchaudio를 찾았지만; 그 전제가 틀렸다. 일치해야 할 것은 CUDA 빌드였다: PyPI의 torchaudio 2.11.0은 CUDA 13.0을 대상으로 하며, 내 torch는 CUDA 13.2였다.
- PyTorch의 테스트 인덱스에 있는 CUDA 13.2 빌드는 오디오 노드를 로드했지만, 안정적인 릴리스가 아니므로 이미지 환경은 여전히 torchaudio 없이 실행된다. (ComfyUI v0.38.0 이상 버전에서는 torchaudio가 전혀 필요하지 않다.)
- 동일한 커밋의 requirements는 다른 버전을 설치했다 (numpy 1.26.4 → 2.5.2, opencv-python 4.10 → 5.0).
- 동일한 워크플로우, 입력 및 시드: 전처리는 거의 동일했지만, 최종 이미지는 다른 디테일을 가진 같은 구성을 보여주었다. 다른 GPU와 torch를 사용했기 때문에, 동일한 시드가 동일한 이미지를 생성하지 못했다.
범위
- 옮긴 내용: 하나의 이미지 워크플로우(라인 아트 및 타일 ControlNet을 사용한 SDXL img2img)를 그대로 옮겼습니다. 즉, 고정된 ComfyUI 커밋, 동일한 커스텀 노드, 그리고 동일한 4개의 모델 파일을 사용했습니다. 목표는 새로운 모델을 시도하는 것이 아니라 이미 작동하던 것을 같은 형태로 구동하는 것이었습니다.
- 이전 환경: Intel Arc 140V 통합 GPU가 장착된 노트북에서 PyTorch의 Intel GPU (XPU) 빌드를 사용하여 실행했습니다.
- 현재 환경: WSL2 내부의 Surface Laptop Ultra(Windows 11 Arm64, NVIDIA RTX Spark N1X)로 옮겼습니다. GPU 공급업체와 CPU 아키텍처가 모두 변경되었습니다.
- 측정한 내용: 무엇이 설치되었고 무엇이 설치되지 않았는지; 두 장치에서 실행하는 2~5번 워크플로우의 재작성 시간; 전처리 과정과 최종 이미지에 대한 출력 차이(평균 차이, PSNR, SSIM).
- 측정하지 않은 내용: 끝부분 근처의 “여기서 멈추는 지점”을 참조하세요.
- 버전 및 인덱스 내용은 제가 원본 글을 작성했던 2026년 10월에 기록된 것입니다.
이 게시물은 torchaudio 문제에 대한 저의 첫 번째 시도와 그 수정 사항을 모두 담고 있습니다.
목표 환경 (The target environment)
| |
|---|
| PC | Surface Laptop Ultra (Windows 11 Arm64, NVIDIA RTX Spark N1X) |
| ... | |
WSL2 메모리: 24GB로 증설
Microsoft의 WSL 구성 문서에 따르면, WSL2는 기본적으로 Windows 전체 메모리의 50%를 사용합니다. 이 노트북은 GPU에 95.5GB를 할당하므로, Windows 자체에는 약 31GB만 남고 WSL2가 사용할 수 있는 공간은 15GB였습니다.
이미지 생성 과정에서는 모델 파일을 CPU 메모리로 읽어 들인 후 GPU로 이동시킵니다. 저는 이 피크 사용량이 8~16GB에 달할 것으로 추정하여 %USERPROFILE%\.wslconfig 파일을 생성했습니다:
wsl --shutdown을 실행하고 WSL2를 재시작한 후, free -g 명령으로 총 23GB가 표시되었습니다.
결과적으로, WSL2 메모리 사용량은 첫 번째 생성 과정에서 최대 5.5GiB에 도달했기 때문에, 24GB는 충분했습니다. 이 워크플로우의 경우, 기본값인 15GB로도 충분했을 수 있습니다. 저는 나중에 더 큰 모델을 위해 24GB를 유지했습니다.
ComfyUI 고정 후 설치 전 요구사항 읽기
저는 이전 노트북에서 실행했던 정확한 커밋들을 확인했습니다:
설치하기 전에, 저는 두 개의 requirements.txt 파일 모두에서 PyPI가 아닌 다른 곳에서 가져오는 라인들(예: git+ 라인, URL, -e, --index-url 등)을 확인했습니다.
grep -nE 'git\+|https?://|^-e|--index-url|--extra-index-url|--find-links' requirements.txt
어떤 파일에도 해당 라인은 없었습니다.
PyTorch: 공식 CUDA 빌드가 그대로 설치됨
이 노트북의 초기 설정 때와 마찬가지로, 저는 Linux Arm용 공식 CUDA 13.2 빌드를 설치했습니다:
torch 2.14.1+cu132
cuda.is_available() True
NVIDIA RTX Spark N1X (6144-core Blackwell RTX GPU)
...
이 GPU는 컴퓨트 캐패빌리티(compute capability)가 12.1이지만, 아키텍처 목록에는 sm_121이 없고 12.0에서 멈춥니다. 그럼에도 불구하고 생성은 GPU에서 실행되었습니다. NVIDIA의 Blackwell 호환성 가이드에 따르면, 한 컴퓨트 캐패빌리티를 위해 빌드된 cubin은 동일한 메이저 버전과 같거나 더 높은 마이너 버전을 가진 GPU에서 실행됩니다. 12.0 코드가 12.1에서 실행되는 것은 이와 일치합니다.
torchaudio: 버전 번호가 아닌 CUDA 버전이 불일치함
이 커밋에서는 ComfyUI의 requirements.txt에 torch, torchvision, 그리고 torchaudio가 나열되어 있습니다. 오직 torchaudio만 설치에 실패했습니다.
첫 번째 시도: torch와 동일한 버전을 찾아보기, 그 후 제거하기
torch는 2.14.1이었으므로, 저는 torchaudio 2.14.1을 찾았습니다.
PyTorch의 CUDA 13.2 인덱스에서 가장 최신 torchaudio는 2.2.0 aarch64 빌드였습니다. aarch64 또는 다른 플랫폼에 대해 더 새로운 버전은 없었습니다. 해당 인덱스에서 torch, torchvision, torchaudio를 함께 설치하려고 시도했을 때 Cannot install torch and torchaudio==2.2.0 because these package versions have conflicting dependencies 및 ResolutionImpossible 오류가 발생하며 중단되었습니다.
PyPI에서는 최신 버전이 2.11.0이었고, 2.14.1은 없었습니다.
CUDA 13.0 및 12.8 인덱스 역시 torchaudio 2.11.0에서 중단되었습니다.
그래서 저는 CUDA 13.2 인덱스에서 torch와 torchvision만 설치하고, torchaudio 라인을 제거한 ComfyUI의 요구사항(requirements)을 설치했습니다.
저는 또한 pip 제약 파일(constraints file)을 사용하여 torch와 torchvision을 고정(pinning)했습니다. requirements에 있는 torch 라인에는 버전이 없었기 때문에, 의존성 해결 과정에서 CUDA 13.2용 torch가 PyPI의 torch로 대체될까 봐 걱정했습니다. 당시 저는 PyPI의 Linux Arm torch가 CPU 전용 빌드라고 생각했습니다. 나중에 PyPI의 aarch64 wheel의 METADATA를 읽어보니, 그것이 CUDA 13.0에 의존한다는 것을 알게 되었습니다. 따라서 CPU 빌드가 될 위험은 없었지만, 여전히 13.2가 13.0으로 대체되는 것은 원치 않았습니다. 실제로 교체되는 현상은 목격하지 못했습니다. 고정(pinning) 후에도 torch는 2.14.1+cu132로 유지되었습니다. PyPI의 Linux Arm 빌드가 CUDA 13.0을 목표로 한다는 사실은 아래에서 다시 언급됩니다.
대략적으로 (제가 실제로 입력한 명령어는 아님):
pip freeze | grep -E '^(torch|torchvision)==' > constraints.txt
grep -v '^torchaudio' requirements.txt > requirements-noaudio.txt
pip install -r requirements-noaudio.txt -c constraints.txt
유일한 영향은 세 개의 오디오 노드 파일(nodes_audio.py, nodes_lt_audio.py, nodes_audio_encoder.py)이 시작 시 로드되지 않은 것이었습니다. 이미지 워크플로우는 이들을 사용하지 않습니다.
나중에: 같은 숫자를 찾으려 한 것이 실수였습니다
torchaudio의 공식 설치 페이지에는 다음과 같이 나와 있습니다:
TorchAudio 2.11은 PyTorch 2.11과 모든 향후 PyTorch 버전에서 작동합니다
PyPI의 METADATA에서도 이를 확인했습니다. torchaudio 2.10.0은 Requires-Dist: torch==2.10.0을 요구하지만, 2.11.0에는 torch 요구 사항이 없습니다. 2.11 버전부터는 torchaudio가 특정 torch 버전에 종속되지 않습니다. torchaudio 번호 2.14.1을 찾는 것은 잘못된 전제였습니다.
PyPI의 2.11.0 설치 후 임포트 실패
그래서 이미지의 가상 환경(venv) 사본에 PyPI의 torchaudio 2.11.0 (aarch64)을 설치했습니다. 원본 이미지 venv는 건드리지 않았습니다.
제약 조건이 여전히 유지된 상태에서, pip은 torchaudio 2.11.0만 설치했고 torch는 교체되지 않았습니다. 하지만 임포트가 실패했습니다:
RuntimeError: Detected that PyTorch and TorchAudio were compiled with different CUDA versions. PyTorch has CUDA version 13.2 whereas TorchAudio has CUDA version 13.0. Please install the TorchAudio version that matches your PyTorch version.
PyPI의 aarch64 torchaudio는 CUDA 13.0용으로 빌드되었고, torchaudio는 임포트 시점에 (torchaudio/_extension/utils.py의 _check_cuda_version()에서) 이 CUDA 버전을 torch와 비교합니다. 제 torch는 CUDA 13.2였습니다. ComfyUI는 시작했지만, 오디오 노드는 동일한 오류로 실패했으며, 노드 수는 torchaudio가 전혀 없을 때와 마찬가지로 706개였고 (그중 20개가 오디오 관련),
pip이 성공했다는 것이 작동한다는 의미는 아니었습니다. 일치해야 했던 것은 버전 번호가 아니라 CUDA 버전이었습니다.
테스트 인덱스에 존재하는 CUDA 13.2 빌드의 2.11.0 버전
작성 시점(2026년 10월)에 안정적인 CUDA 13.2 인덱스에는 torchaudio 2.11 버전이 없었습니다. PyTorch의 테스트 인덱스에는 torchaudio-2.11.0+cu132-cp312-cp312-manylinux_2_28_aarch64.whl 파일이 있었습니다. 저는 torch를 건드리지 않도록 --no-deps 옵션을 사용하여 이를 설치했습니다. torch와 torchvision은 그대로 유지되었습니다.
대략적으로 (실제 명령어는 아님):
pip install --no-deps --index-url https://download.pytorch.org/whl/test/cu132 "torchaudio==2.11.0+cu132"
torch 및 torchaudio의 __version__, 그리고 torch.cuda.is_available():
2.14.1+cu132 2.11.0+cu130 True
torchaudio의 __version__은 "2.11.0+cu130"을 나타내지만, import 시의 CUDA 검사는 통과했습니다.
- MelSpectrogram 및 resample이 GPU에서 실행되었습니다.
- ComfyUI 시작 로그에서 "torchaudio missing" 메시지가 사라졌고, 오디오 노드들이 오류 없이 로드되었습니다.
- 노드는 706개에서 732개로 증가했으며, 오디오 노드는 20개에서 45개로 늘어났습니다 (LoadAudio, SaveAudio, VAEEncodeAudio, VAEDecodeAudio 등).
- 이미지 워크플로우의 이미지 하나도 이 상태에서 끝까지 실행되었습니다.
여전히 이미지 환경에는 속하지 않음
테스트 인덱스는 안정적인 릴리스 전에 빌드가 위치하는 곳입니다. 안정적인 CUDA 13.2 인덱스에는 (글 작성 시점 기준) 2.11 버전이 없었기 때문에, 저는 torchaudio를 이미지 환경에서 제외했습니다. 위의 결과는 복사된 venv(가상환경)에서 나온 것입니다.
ComfyUI 측에서는 torchaudio가 requirements에서 제거되었습니다 (#16457, "torchaudio 의존성 제거"). PR 설명에는 "안정적인 cu132 빌드 없음"이라고 명시하며, 안정적인 CUDA 13.2 빌드가 없다는 것을 이유로 들었습니다. v0.37.0의 requirements는 torchaudio를 포함하지만, v0.38.0은 그렇지 않습니다. 제가 커밋을 고정했기 때문에, 제거되기 이전 버전의 버전을 사용하게 되었습니다.
사용자 정의 노드: 사용하지 않는 의존성 건너뛰기
사용자 정의 노드(comfyui_controlnet_aux)의 requirements에서 저는 mediapipe를 제외했습니다. 이 라이브러리는 face, pose 및 hand 노드에서 사용되지만, 현재 워크플로우에서는 사용하지 않습니다.
PyPI 상에서 mediapipe 0.10.33 버전은 Linux aarch64 wheel이 없지만, 더 최신 버전인 1.1.1은 있습니다. 이 사용자 정의 노드 팩이 1.x 버전과 작동하는지는 확인하지 않았습니다. 필요할 때 확인할 예정입니다.
설치 후 pip list를 통해 mediapipe, insightface, torchaudio, 그리고 모든 Intel GPU 패키지(intel 또는 xpu가 포함된 이름)가 설치되지 않았음을 확인했습니다.
requirements 파일 중 어느 것도 onnxruntime을 나열하지 않았기 때문에 onnxruntime도 설치되지 않았습니다. 시작 시 DWPose (pose estimation)가 CPU의 OpenCV로 폴백(fallback)한다는 경고가 나타납니다. 이 워크플로우 역시 이를 사용하지 않습니다.
패키지 버전이 구형 노트북과 일치하지 않음
같은 커밋의 요구 사항(requirements)에서 가져왔음에도 불구하고, 설치된 버전들이 이전 노트북과 일치하지 않았습니다. 대부분의 요구 사항은 버전을 고정(pin)하지 않습니다 (일부는 numpy>=1.25.0처럼 최소값만 설정). 따라서 설치 시점에 가장 최신인 버전이 자동으로 적용됩니다.
| Package | Old laptop (마이그레이션 당시) | Surface (WSL2) |
|---|
| torch | Intel GPU (XPU) build | 2.14.1+cu132 |
| ... | | |
'Old laptop' 열은 마이그레이션 시점을 기준으로 합니다. 그 이후로 이전 노트북은 Python 3.12에서 3.14로, numpy는 2.5.4로, opencv-python은 4.14로 업데이트되었습니다. 아래의 출력 비교는 이 더 새로운 버전들을 사용하여 수행되었습니다.
저는 Surface를 이전 노트북과 동일한 수준으로 맞추지 않았습니다. 마이그레이션 당시, numpy는 1.x에서 2.x로, opencv-python은 4.x에서 5.x로 건너뛰었습니다: 주요 버전 점프(major-version jumps)가 발생했습니다. 출력 변화에 대한 내용은 아래 "Comparing the outputs" 섹션을 참고해 주십시오.
설치 후 전체 pip freeze 결과를 파일로 저장했기 때문에, 나중에 차이가 발견되더라도 어떤 패키지가 달랐는지 추적할 수 있습니다.
모델: 배치하기 전에 검증됨