I reverse-engineered Intel's NPU stack and got custom C kernels running on its programmable SHAVE cores
Intel NPU 스택을 역공학해 프로그래밍 가능한 SHAVE 코어에서 C 커널 실행
npunlock은 Intel NPU의 그래프 실행 경로를 역공학해, 사용자가 작성한 C 커널을 ACT-SHAVE 코어에서 실행하도록 연결하는 도구입니다. Meteor Lake의 NPU3720과 Windows x64에서 검증했으며, 현재 정적 텐서와 제한된 커널·레이아웃만 지원합니다.
- 주제
AI 요약
Intel NPU는 프로그래밍 가능한 SHAVE 코어를 탑재하지만, 공개 소프트웨어 스택은 지원되는 연산으로 구성한 그래프를 실행하는 방식만 제공합니다. 사용자가 C 코드를 커널로 컴파일해 그래프에 넣는 경로는 공개하지 않습니다. npunlock은 Windows NPU 드라이버가 만드는 그래프와 실행 구조를 살펴 이 빈틈을 연결합니다. 현재 검증된 환경은 Windows x64와 Meteor Lake 기반 NPU3720입니다.
실행 경로와 구현
도구는 MoviTools의 C 컴파일러로 사용자 코드를 ACT-SHAVE용 ELF 바이너리로 만든 뒤, Intel 드라이버와 컴파일러가 생성한 그래프에서 호환되는 ACT 커널을 교체합니다. 기존 컴파일러와 드라이버는 그래프 구성, 메모리 배치, 스케줄링, 동기화를 계속 담당합니다. 따라서 Intel 스택 전체를 대체하지 않고 선택한 연산에 사용자 커널을 끼워 넣습니다. Python, CLI, 네이티브 C 인터페이스를 제공하며, OpenVINO는 런타임이나 컴파일러 프런트엔드로 필요하지 않습니다. 다만 설치된 Intel 드라이버가 읽도록 OpenVINO 형식 IR을 출력합니다.
GELU 예제와 지원 범위
저장소의 FP32 GELU 예제는 Python에서 그래프 입력을 만들고 C 커널을 npu.custom 연산으로 등록해 실행합니다. 커널은 입력·출력 텐서 주소와 원소 수를 얻는 NPU3720 전용 헤더를 사용합니다. GELU 계산 결과는 NumPy 기준값과 비교합니다. 작성자는 아직 체계적인 성능 측정을 하지 않았으므로 속도 향상을 주장하지 않는다고 밝혔습니다.
대신 FP32 GELU에서 확인한 실행 경로 차이를 설명합니다. 테스트한 일반 OpenVINO/NPU 경로는 FP32 입력을 FP16으로 변환한 뒤 GELU를 계산하고 다시 FP32로 변환합니다. 이 과정은 세 번의 호출을 거치며 정밀도 손실도 생깁니다. npunlock의 사용자 커널은 GELU를 FP32로 직접 계산해 ACT-SHAVE 호출 한 번으로 처리합니다. 컨볼루션이나 행렬 곱셈 같은 affine 연산의 속도 향상보다는, GELU처럼 비선형 연산이나 드문 활성화 함수, 정밀도가 다른 구현에 활용할 여지가 있다고 설명합니다.
현재 정적 FP16 단항·이항 커널과 검증된 FP32 단항 커널을 지원합니다. 한 그래프에서 독립적인 FP32 단항 분기와 FP16 이항 분기를 함께 실행하는 사례도 있습니다. 다만 연결된 혼합 정밀도 변환 그룹은 아직 그래프에서 찾아낼 수 없으며, 지원 범위는 호환되는 ACT 캐리어와 알려진 텐서 레이아웃으로 제한됩니다. 다른 NPU 세대와 Linux 환경은 검증되지 않았습니다. MoviTools는 배포하지 않으며, 테스트된 도구 체인은 Lenovo의 구형 드라이버 패키지에서 추출해야 합니다. 프로젝트는 해당 드라이버를 설치하거나 구버전으로 내리라고 안내하지 않습니다.
Reddit 반응
- @u/hsfzxjy — Intel은 수백만 대의 AI PC에 NPU를 탑재했지만, 일반 소프트웨어 스택에서는 SHAVE 코어의 프로그래밍 기능을 공개하지 않았습니다. OpenVINO는 지원되는 연산으로 그래프를 만들면 컴파일러가 NPU 실행 코드를 생성하는 추상화를 제공합니다. 하지만 C 코드를 커널로 컴파일해 그래프에 넣는 저수준 경로는 제공하지 않습니다. 오래된 OEM 드라이버 패키지에 남아 있던 Intel/Movidius 도구 체인에서 C 코드를 ACT-SHAVE ELF로 만드는 컴파일러를 찾았습니다. 이어 네이티브 그래프 안에서 ELF가 표현되는 방식과 ACT 작업 연결 구조를 조사했습니다. 최종적으로 C 소스, SHAVE ELF, Intel 컴파일 그래프, 호환 ACT 커널 교체, NPU 실행으로 이어지는 경로를 실제 하드웨어에서 작동시켰습니다. 프로젝트는 실험 단계이며 Windows x64와 Meteor Lake/NPU3720, 좁은 텐서 레이아웃과 ACT 캐리어만 시험했습니다. 이해하지 못한 그래프는 추측으로 수정하지 않고 거부합니다.
- @u/HeDo88TH — 실제로 작동한다면 정말 대단한 작업입니다.
- @u/streetster_ — 성능은 어느 정도인가요? 무엇과 비교할 수 있나요? 그래도 훌륭한 작업입니다.
- @u/hsfzxjy — 아직 체계적인 성능 벤치마크를 하지 않았으므로 측정하기 전에는 속도 향상을 주장하지 않겠습니다. 지금 목표는 쓸 수 있는 경로를 입증해 커널 전문가가 구현하고 튜닝할 수 있게 여는 것입니다. FP32 GELU에서는 일반 경로가 FP32를 FP16으로 바꾸고 GELU를 계산한 뒤 다시 FP32로 변환합니다. npunlock은 나머지 그래프를 그대로 두고 해당 연산만 FP32 사용자 커널로 바꿔 한 번의 ACT-SHAVE 호출로 처리합니다. 컨볼루션이나 행렬 곱셈보다 비선형 연산, 드문 활성화 함수, 수치 안정성을 높이는 정밀도별 구현에 도움이 될 가능성이 있습니다.
- @u/fragment_me — 프로그래머에게 공개하지 않는다면 이 NPU는 어떤 용도로 쓰나요?
- @u/hsfzxjy — Intel은 사용자가 지원되는 연산으로 그래프를 만들면 컴파일러가 NPU 실행 방법을 정하는 고수준 사용을 기대합니다. SHAVE 코어는 식당 주방과 비슷합니다. 손님은 메뉴에 있는 요리를 주문할 수 있지만, 주방에는 메뉴에 없는 요리를 만들 장비도 있습니다. npunlock은 그 주방에서 직접 요리하는 방법을 찾는 셈입니다. 하드웨어 인터페이스를 공개하지 않는 이유는 NPU 세대가 빠르게 바뀌는 상황에서 하드웨어 세부사항을 드러내면 호환성 부담이 커지기 때문일 수 있다고 추측합니다.
- @u/marssaxman — Intel에서 Myriad X 펌웨어를 조금 다뤘습니다. 칩에 더 직접 접근할 수 있기를 늘 바랐습니다. OpenVINO를 거치지 않고도 흥미로운 일을 할 수 있었겠지만, 당시 회사 전략은 여러 하드웨어 아키텍처에 공통 API를 제공하는 데 있었습니다. SHAVE뿐 아니라 DNN 유닛, 즉 신경망 컴퓨트 엔진에도 접근할 수 있을지 궁금합니다.
- @u/hsfzxjy — Myriad X를 다뤄본 경험을 들려주셔서 감사합니다. 공통 API 전략은 조사한 스택을 이해하는 데도 도움이 됩니다. 현재 Intel 컴파일러가 지원 그래프 연산을 위해 만드는 DPU/NCE 작업은 그대로 두고 ACT/SHAVE 커널만 교체합니다. DPU를 직접 프로그래밍하는 기능은 아직 구현하지 않았습니다. DPU는 임의 코드를 올리는 SHAVE와 달리 구조화된 텐서 작업을 설정하는 고정 기능 장치에 가까워 보입니다. 그래프에 DPU 작업 설명자가 있으므로 저수준 명령 형식을 조사하는 일을 다음 주제로 생각하고 있습니다.
- @u/Spare_Side_5907 — 이 DLL들은 어떻게 구하나요? 확인된 버전은 moviCompile64.dll 00.114.11.4207, moviAsm64.dll 1.13.16 64-bit, moviLLD64.dll 3.0.9입니다. 컴파일러는 Movidius Compiler v00.114.11 Build 4207, LLVM 14.0.0 기반이라고 표시합니다.
- @u/hsfzxjy — 안내에 따라 구형 Lenovo 드라이버 패키지를 내려받아 압축을 풀면 됩니다.
원문: GitHub / 번역·요약: Trawling