🔥 Python 패키지, 아직도 2009년 CPU에 맞춰 빌드된다
강의 목차

pip install numpy를 실행할 때마다 내 컴퓨터에 설치되는 바이너리가 2009년 수준의 CPU 명령어로 빌드된 거라는 사실을 알고 있었나? 나는 몰랐다. Talk Python To Me 에피소드 #544를 듣다가 이 사실에 멈칫했다. AVX2? SSE4? 내 CPU가 지원하는 최신 명령어 세트는 wheel 파일 어디에도 기록되지 않는다. 인스톨러는 그런 게 있는지조차 모른다.
성능 차이가 10배에서 20배까지 난다고 한다. 2009년 대비.
2009년에 멈춘 Python 바이너리
Python wheel의 파일명에는 세 가지 정보가 들어간다. OS(Windows, macOS, Linux), CPU 아키텍처(x86-64, ARM), 그리고 Python ABI 버전. 여기까지가 전부다. NumPy 같은 패키지가 내부적으로 SIMD 벡터 연산을 쓰더라도, wheel 파일명에 "이 바이너리는 AVX2가 필요합니다"라고 적을 방법이 없다.
결과적으로 모든 배포 바이너리는 가장 오래된 CPU에서도 돌아가도록 빌드된다. Intel x86-64 기준으로 2009년 이후 추가된 하드웨어 기능은 전부 사용할 수 없다. GPU는 말할 것도 없다. CUDA 버전? 인스톨러가 알 방법이 없다. PyTorch를 설치하려면 별도의 인덱스 URL을 직접 설정해야 하고, 그 설치 페이지는 퍼즐북 수준이다.
에피소드에서 Quansight의 Ralf Gommers가 한 말이 인상적이었다. "Intel x86-64 기본 wheel로 빌드하면 2009년 CPU 기능만 쓸 수 있다. 2019년이나 2023년 CPU 기능과의 성능 차이는 10배에서 20배." SIMD 벡터화가 필요한 과학 계산 분야에서 이건 치명적인 제약이다.
NumPy가 선택한 영웅적 우회로
NumPy는 이 문제를 자체적으로 해결했다. CPU dispatcher라는 시스템을 만들어서, 하나의 소스 파일을 Haswell, Skylake 등 여러 CPU 아키텍처별로 각각 컴파일한 뒤 하나의 확장 모듈로 합친다. 런타임에 CPU를 감지해서 적절한 코드 경로로 디스패치하는 구조다.
이게 돌아가려면 아키텍처별 전문가가 필요하다. Intel은 수년간 엔지니어를 붙여 x86 코드 경로를 최적화했고, ARM은 별도의 NumPy 메인테이너가 ARM 명령어를 관리한다. 4명의 전담 팀이 이 아키텍처를 유지보수한다. Ralf는 "이건 확장 가능한 프로세스가 아니다"라고 솔직하게 말했다.
게다가 모든 아키텍처별 코드를 하나의 바이너리에 합치면 크기가 커진다. 이런 바이너리의 별명이 "Fatbin"이다. 이름에서 느껴지는 그대로다.
SciPy는 이미 AVX2와 ARM Neon 구현 코드를 갖고 있다. 하지만 빌드해서 배포할 방법이 없어서 그냥 묻어두고 있다. scikit-learn, Pandas, Pillow도 마찬가지다. SIMD 코드를 넣을 수는 있지만 배포할 수단이 없다.
PyTorch: 900MB짜리 wheel의 세계
GPU 쪽은 상황이 더 극적이다. PyTorch의 기본 wheel은 약 900MB다. 여러 CUDA 아키텍처를 하나의 바이너리에 전부 넣기 때문이다. PyTorch 팀은 1GB 아래로 유지하려고 사투를 벌인다고 한다.
사용자 입장에서는 더 괴롭다. PyTorch 설치 페이지에 가면 CUDA 버전, OS, 패키지 매니저를 직접 조합해서 설치 명령어를 만들어야 한다. pip install torch만으로는 내 GPU에 맞는 빌드가 깔리지 않는다. vLLM 같은 PyTorch 확장 패키지는 설치 난이도가 한층 더 높다.
에피소드에서 Astral의 Charlie Marsh가 핵심을 짚었다. "wheel 스펙에는 OS와 CPU 아키텍처가 포함되어 있고, 인스톨러는 그걸 감지할 줄 안다. 하지만 CUDA 버전이나 CPU 명령어 세트 같은 건 스펙에 없다. 인스톨러가 어떤 PyTorch 빌드를 설치해야 하는지 판단할 수 없다."
Wheel Variants가 적용되면 PyTorch를 CUDA 아키텍처별로 쪼개서 배포할 수 있다. 900MB짜리 하나 대신 200~250MB짜리 여러 개. 인덱스 서버 대역폭도 줄고, 사용자 다운로드 시간도 줄고, PyPI 인프라 비용도 줄어든다.
14개 이상의 회사가 모였다
이 문제를 해결하기 위해 만들어진 것이 Wheel Next 프로젝트다. NVIDIA의 Jonathan Dekhtiar, Quansight의 Ralf Gommers, Astral의 Charlie Marsh가 핵심 멤버다. 참여 기업 목록이 인상적이다. AMD, Anaconda, Astral, Google, Huawei, Intel, Meta, NVIDIA, Preferred Networks, Quansight, Red Hat, 그리고 scikit-learn 뒤의 Probabl까지.
2025년 3월에는 약 20개 회사가 참석한 대면 서밋이 열렸다. PyTorch 팀, JAX 팀이 각자의 고충을 발표했다. Jonathan은 이 과정을 "스타트업 같았다"고 표현했다. 프로토타입을 만들고, 피드백을 받고, 수정하는 사이클을 1년간 반복했다.
슈퍼컴퓨터 패키지 매니저 Spack의 archspec 라이브러리에서 영감을 받았다. archspec은 CPU 마이크로아키텍처(Haswell, Skylake 등)를 체계적으로 분류하고 JSON으로 관리한다. Jonathan은 이 설계를 "순수한 천재성"이라고 평가했다. Conda-Forge와 Nix에서도 아이디어를 가져왔다.
프로젝트 이름 자체가 Faster CPython에서 영감을 받은 것이다. Microsoft가 주도한 Faster CPython이 인터프리터 성능에 집중했다면, Wheel Next는 패키징 쪽에서 같은 크로스 인더스트리 에너지를 만들겠다는 선언이다.
Wheel Variants: 개념은 단순하다
핵심 아이디어는 이렇다. wheel 파일에 "이 바이너리는 CUDA 12.6용입니다" 또는 "이 바이너리는 AVX2를 사용합니다" 같은 메타데이터를 추가한다. 인스톨러가 그걸 읽어서 사용자 환경에 맞는 빌드를 자동으로 선택한다. 끝.
기존처럼 platform tag를 하나하나 추가하는 방식이 아니다. 200개 태그를 새로 정의하고 2년 뒤에 또 200개를 추가하는 식은 유지보수 지옥이다. 대신 범용적인 variant 메타데이터 시스템을 설계했다. 패키지 제작자가 임의의 하드웨어 요구사항을 선언하고, 인스톨러는 variant provider 플러그인을 통해 사용자 환경을 감지하고 매칭한다. 확장 가능하고, 중앙 관리가 필요 없는 구조다.
PEP 817에서 PEP 825로: "역대 최장 PEP"의 분리
이 제안은 PEP 817 — Wheel Variants: Beyond Platform Tags로 처음 제출되었다. 비공식적으로 "역대 가장 긴 PEP"라는 타이틀을 얻은 문서다. 패키지 포맷, 인스톨러 동작, 레지스트리 지원, 빌드 백엔드 연동까지 Python 패키징 스택 전체에 영향을 미치기 때문에 그럴 수밖에 없었다.
너무 커서 분리가 필요했다. 첫 번째 조각이 PEP 825 — Wheel Variants: Package Format이다. 2026년 2월 17일에 생성되어 현재 Draft 상태다. wheel 파일 포맷 변경에 집중하는 최소 실행 가능 PEP다. 인스톨러 동작, 레지스트리, 빌드 백엔드 관련 내용은 후속 PEP 3~4개로 나뉘어 나올 예정이다.
PEP 프로세스는 느리다. 편집자들이 문서 형식만 검토하는 데 한 달 이상 걸렸다. 그 다음엔 Python Discourse에서 커뮤니티 리뷰가 진행된다. 비스레드 포럼에서 이 복잡한 멀티 컴포넌트 논의를 하는 건 고된 일이다.
하지만 PEP 825가 Draft로 병합된 것은 실질적 진전이다. 에피소드에서 Jonathan은 free-threaded Python을 만든 Sam Gross를 언급했다. "Free-threading에 대한 회의론이 컸을 때 Sam은 말이 아니라 작동하는 프로토타입으로 증명했다. 우리도 같은 전략을 택했다."
그 프로토타입 이야기는 Part 2에서 이어진다.
참고 자료
- Talk Python To Me #544: Wheel Next + Packaging PEPs — 이 글의 원본 에피소드
- PEP 817 — Wheel Variants: Beyond Platform Tags — Wheel Variants의 전체 제안서
- PEP 825 — Wheel Variants: Package Format — PEP 817에서 분리된 첫 번째 PEP (Draft)
- Wheel Next 프로젝트 — 프로젝트 공식 사이트, 서밋 자료 포함
- NumPy CPU Dispatcher — NumPy의 SIMD 디스패치 시스템 문서
- pypackaging-native — Ralf Gommers가 만든 네이티브 코드 패키징 문제 가이드
시리즈: Python Wheel Variants — 패키징의 하드웨어 인식 혁명








